読者です 読者をやめる 読者になる 読者になる

Perlの食えない事情 - 演算子編

Perlの食えない事情 より
おっと、そうです、Perlには演算子が多すぎるのでした。せっかくの機会なので、Perl演算子を紹介します。

ビーナス演算子: 0+, +0

数値として評価してくれます。意外とよく見かけますね。
なぜこの演算子を使う必要があるのかというと、Perlは文字列と数値を明確に区別できないからです。scalarを文字列として解釈するならば文字列として、

print 0+ '10';    #=> 10
print 0+ '123b';  #=> 123
print '1.2e3' +0; #=> 1200
print [] +0;      #=> 4303367864

ちなみに、文字列として評価するときにはこのようにするとかっこいいと言われています。

$obj.q();

一見メソッド呼び出しのように見えますが

$obj . '';

と等価です。

ベビーカー演算子: @{[ ]}

文字列の中に式を展開することができます。
array refをその場でデリファレンスしています。したがって、リストコンテキストで評価されることに注意しましょう。

print "1 + 1 = @{[ 1 + 1 ]}\n";
print "localtime: @{[ scalar localtime ]}\n";

バン!バン!演算子: !!

真偽値として評価してくれます。
Perlのモジュールは最後にtrueを返す必要があり、ほとんどの人はファイルの最後に1;を書きますが、わざと真偽値を返すためにこう書く人もいます:

!!1;

イヌイット演算子: }{

イヌイットは鼻と鼻をこすり合わせてあいさつをするみたいですね。そう、この演算子のように。
この演算子はENDブロックと*似たような*動作をします。ワンライナーのときに使うと便利です。

perl -lne '}{print$.'

シャクトリムシ演算子: ~~

パターンマッチ演算子?違います。コイツは単項演算子のシャクトリムシなのです。
実はscalar()と同じ動作をします。しかも"scalar"よりも4文字短いのです。

print ~~localtime; #=> Sun Feb  3 01:43:33 2013

枝の上でおやすみ中のシャクトリムシ演算子: ~-, -~

優先順位が高いインクリメント(-~)、デクリメント(~-)演算子です。

宇宙ステーション演算子: -+-

優先順位が高いビーナス演算子(0+, +0)です。

print 0+ '20GBP' x 3;  #=> 20
print -+- '20GBP' x 3; #=> 202020

Goatse演算子: =( )=

説明: この演算子の意味を理解できないのなら、あなたは運がいい。画像検索しないことをお勧めする。

うーん。この説明はちょっと意味がわかりませんね。今ちょうど検索ができない状況にあるので、誰かに確かめていただきたい :)
冗談はさておき、この演算子はどのようにして使うのか気になりますよね?右手に式を渡しておくと、左手に返り値の要素数が返ってきます。もちろんケツからは@がでてきます。

$n =(@c)= "abababab" =~ /a/g; # $n = 4; @c = qw( a a a a )

例えば、PATHの個数だけを調べたいときに使えます:

$count =()= split /:/, $ENV{PATH};
$count = @{[ split /:/, $ENV{PATH} ]}; # ベビーカー演算子

Xウィング(燃)演算子: =< >=~

ファイルから一行読み込み、その際に正規表現のキャプチャを受け取ることができます。

# pick named fields from input
@data{@fields} =<>=~ $regexp;

Xウィングに乗ることもできます:

# use the source, Luke!
$luke = \*DATA;
@data{@fields} =<$luke>=~ $regexp;

タコ演算子: ~~<>

凧。またの名をsperm演算子
ファイルから一行読み込みます。リストに埋め込むときに便利です:

@triplets = ( ~~<>, ~~<>, ~~<> );

ダブルブレード演算子: <> m;

Perlで複数行コメントを実現するには

=pod
  comment
=cut

とするのがよく知られています。でも少し面倒ですよね?そうです、そんなときにはダブルブレード演算子が使えます:

<<m=~m>>
  Use the secret operator on the previous line.
  Put your comments here.
  Lots and lots of comments.

  You can even use blank lines.
  Finish with a single
m
;

正確にはコメントではないので注意してください。

マイナスドライバー演算子: -=!, -=!!

$x -=!! $y     # $x-- if $y;
$x -=!  $y     # $x-- unless $y;

プラスドライバー演算子: +=!, +=!!

$x +=!! $y;    # $x++ if $y;
$x +=!  $y;    # $x++ unless $y;

ポジドライバー演算子: x=!, x=!!

$x x=!! $y;    # $x = '' unless $y;
$x x=!  $y;    # $x = '' if $y;

トルクスドライバー演算子: *=!, *=!!

$x *=!! $y;    # $x = 0 unless $y;
$x *=!  $y;    # $x = 0 if $y;

ウインクファットカンマ演算子: ,=>

ファットカンマ演算子(=>)は次のようなケースで不便です。

use constant APPLE   =>  1;
use constant CHERRY  =>  2;
use constant BANANA  =>  3;

my %hash = (
    APPLE   =>  "green",
    CHERRY  =>  "red",
    BANANA  =>  "yellow",
);
#=> %hash = ( "APPLE", "green", "CHERRY", "red", "BANANA", "yellow" );

本当は、constantで宣言したものがキーとなって欲しかったのですが、キーがそのまま文字列として解釈されてしまいました。
そんなときにはウインクファットカンマ演算子(,=>)を使いましょう:

use constant APPLE   =>  1;
use constant CHERRY  =>  2;
use constant BANANA  =>  3;

my %hash = (
    APPLE   ,=>  "green",
    CHERRY  ,=>  "red",
    BANANA  ,=>  "yellow",
);
#=> %hash = ( 1, "green", 2, "red", 3, "yellow" );

エンタープライズ演算子: ()x!!

演算子の名前はスタートレックに由来しているらしいです。

my @shopping_list = ('bread', 'milk');
push @shopping_list, 'apples'   if $cupboard{apples} < 2;
push @shopping_list, 'bananas'  if $cupboard{bananas} < 2;
push @shopping_list, 'cherries' if $cupboard{cherries} < 20;
push @shopping_list, 'tonic'    if $cupboard{gin};

エンタープライズ演算子を使うと以下のように書くことができます:

my @shopping_list = (
    'bread',
    'milk',
   ('apples'   )x!! ( $cupboard{apples} < 2 ),
   ('bananas'  )x!! ( $cupboard{bananas} < 2 ),
   ('cherries' )x!! ( $cupboard{cherries} < 20 ),
   ('tonic'    )x!! $cupboard{gin},
);


参考にさせていただきました: