Perlは文法上、(右)二重矢印「=>
」をカンマ「,
」と同義としている。カンマとの違いとして、二重矢印の左オペランドにbare wordを置くと文字列化される。これによって、ハッシュなど二つの値の組を書いたときにそれっぽく見える。
そこに、罠がある。常識で考えて二重矢印の右オペランドはscalar contextだろう…と思いきや、なんとlist (array) contextなのだ。次のようなコード断片を考える。
1 2 3 4 |
my $conn = Client->connect(server => $config->server, username => $username, password => $password, timeout => 30); |
単体で見れば、まったく問題なさそうに見える。しかし、$config
のserver
メソッドが気を利かせて、scalar contextならプライマリサーバの単値、list contextなら全サーバの配列を返す、のようなことをしてくれた瞬間、破綻してしまう。たとえば、$config
が要素二つの配列を返すと、connect()
メソッドに渡す引数列は('server', 'host1', 'host2', 'username', 'someone', 'password', 'something', 'timeout', 30)
のようになり、これをハッシュで受ければ('server' => 'host1', 'host2' => 'username', 'someone' => 'password', 'something' => 'timeout', 30 => undef)
となってひどいことになる。また、取得できないときに空の値(undef
や''
)でなく空配列(()
)を返すような実装になっていても同様だ。
Perl5のbare wordやcontextに関してはいろいろ疑問を持っていて、いちばん痛い例(文法エラーにも型エラーにもならず、例えば上の例では奇数個の配列が返るときなど顕在化すらしない)がこれなのだが、Larry Wallがその「人間の意図をできるだけ理解して動く」という哲学を徹底するのなら、二重矢印の右側はscalar contextにすべきだった。ここでリスト展開されてうれしいケースはちょっと思いつかない。
今さらPerl5の文法仕様が変わることはないので、せいぜい注意しよう。さすがにPerl6では、contextの概念が変わったり、二重矢印がPairを生成したり、配列がオブジェクトになったりしているので同じ問題は存在しない。別のひずみがある気がするが、それはいずれ。
Your article helped me a lot, is there any more related content? Thanks!