Edited at

Perl for構文 grep, map の不思議

More than 1 year has passed since last update.

先日触った Net::WebSocket::Serverのソースコードを見ていて気づいたのですが、for構文の使い方が意味不明だったので自分用メモ。

まずサンプルコードからして不思議である。

$_->send_utf8($msg) for $conn->server->connections;

この for 一体なんだろう・・・?

そう思ってServer.pm の中も覗いてみると・・・


Server.pm

sub connections { grep {$_->is_ready} map {$_->{conn}} values %{$_[0]{conns}} }


ふぁっ???

return すら存在しないしなんなのよこれ?!

いろいろ試してみて、return if (ごにょごにょ); みたいなPerl独特の文法を利用したものだと気付いた。

my @a = (1,2,3);

print $_ for @a;

# 123

my @a = (1,2,3);

sub b {$_==@_[0]||&c} # セミコロンも省略可らしい・・・
sub c {print "$_\n"} # return はいらない
b(1) for map {$_} grep {$_} @a;

# 2
# 3

解説

&b() は引数の他に、$_ がそのまま参照可能。

A || B は 式Aが<真>ならそのままreturnとして抜けるので 式Bである&c() へはNOTの役割になる

関数 c() の中では $_ はまだ読めるのでprintすればこの通り。

Perlさん、フリーダムすぎぃ!!!

map grep に似ている。でもどっちかというと foreach

まとめると、



  • for は配列が引数の時、左辺にステートメントがあると、左辺に配列の中身を一つずつ参照して $_ として返してくれる。(shiftはしないので配列は破壊されない)

  • 無名変数 $_ を使用するので、他に無名変数を書き換えるような関数などをかますとヤバイ(evalとかも?)

  • perl は変態言語である

こんな混乱を生みそうな文法はあまり良くないと思うけど、一応こんな書き方があるということは、知っておくべきだと思いました。

え?知ってた?常識? 失礼いたしました・・・。