Help us understand the problem. What is going on with this article?

Perl for構文 grep, map の不思議

More than 3 years have 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 は変態言語である

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

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away