Humanity

Edit the world by your favorite way

Perlの演算子

毒にも薬にもならないエントリ。
なんかPerlについて語ってたらいつの間にか長くなった。


ここでソート用関数で

int
comp_func(const int *a, const int *b)
{
    return *a - *b;
}

とかやると値域が限定されてオーバーフローとか起こすよって話題があって、
あー確かにそうだ、charの場合と混同してたなーとか反省したんだけど、
普通に書くと条件分岐が入って1行で書けないなーとか思った*1


そしたらここ*2見てスペースシップ演算子*3 *4のことを思い出した。
Perlではまぁオーバーフローのことは当然考えなくていいんだけど、ソート用に<=>なんて演算子が用意されてる。
これは何をするかというと、上のcomp_funcがやってることそのもの。
*aのが小さい時は負の値(-1)を返して、同じ時は0を返して、*bのが小さい時は正の値(1)を返す。
これの文字列用の演算子*5がcmp。


これ便利だよねー。
あとqwも便利。
「qw(foo bar baz)」と空白で区切れば
「"foo", "bar", "baz"」と同じ意味になる。
テスト用の配列を用意したい時とかにめちゃくちゃ便利。
http://github.com/tyru/dotfiles/blob/master/sync-dotfilesとかでも使ってる。
っていうか実際のPerlスクリプト見ればいくらでも出てくると思う。


あとqとqq。
これはそれぞれ「'」と「"」と同じ意味なんだけどワンライナーとかに便利。
例えば.htmを.htmlにしたくて

$ perl -e 'for $from (glob "*.htm") { ($to = $from) =~ s/\.htm$/.html/; rename $from, $to }'

とかやりたいとする。
でもWindowsだと'は引用符の意味をなさないので、文字列として囲みたい場合は"を使わなければならない。
そんな時は

$ perl -e "for $from (glob qq(*.htm)) { ($to = $from) =~ s/\.htm$/.html/; rename $from, $to }"

とすればいい。
まぁこのケースに関してはWindows使わなけりゃいーじゃんそもそもワンライナー使わなけりゃいーじゃんで済むかもしれないけど。
Windowsでもコマンドラインだけで*6完結できるのは素晴らしい。
実際のスクリプトでも、例えば「foo」ではなく「"foo"」という文字列を表したい場合、Perlでは

  • "\"foo\""
  • qq("foo")
  • qq{"foo"}
  • qq/"foo"/
  • etc...

のどれでも書ける。



こんな風にPerl演算子は色々面白いのがあって好きだ。
まぁいつの間にかPerlについての話になってたけど、一つつっこむとすれば冒頭のcomp_funcをオーバーフローの危険なく書きたい時は、スレにあったけど

int
comp_func(const int *a, const int *b)
{
    return (*a > *b) - (*a < *b);
}

でおk。*7

*1:つ3項演算子

*2:確かVimの情報を探してて購読したんだと思ったけどブログ主さんPerlerだったのか

*3:ちなみにダイアモンド演算子なんてのもある。確かLarryの娘さんが『パパ、これダイアモンドみたい!』とかなんとか言ったのがきっかけだったとか

*4:追記:「ダイヤモンド演算子は、Larryのお嬢さんのHeidiちゃんが命名しました。ある日、Randalは、自分が書いたトレーニングコース用の教材を見せるために、Larryの自宅を訪問しました。そして、『それ』に対する名前がなくて不便だとLarryにこぼしました。Larryも、『それ』の名前を考えていませんでした。そこにHeidiちゃん(当時8才でした)が割り込んできて、『これってダイヤモンドよ、お父さん』と言いました。そして、<>にはダイヤモンド演算子という名前が与えられたのです。ありがとう、Heidiちゃん!」はじめてのPerl 第3版 p.106

*5:個人的にはPerlみたいな演算子指向言語よりも、C++みたいにオブジェクトによって演算子の意味が違ってくる方が好み

*6:エディタさえ使わずに

*7:可読性と、C++でintじゃなかった場合operator>も必要になる点は置いておく