たぶん世界中のみなさまがハマったことあると思いますが、私も本日ハマりました。
use strict; use warnings; use Data::Dumper; use constant HOGE_KEY => 'hoge'; print Dumper { HOGE_KEY => 'fuga' };
HashRefのキーを定数に切り出してtypoを防ぐ、という意図でこのように書くと何が起こるか?
{hoge => 'fuga'}
ではなく {HOGE_KEY => 'fuga'}
というHashRefが得られます。
=>
演算子(時々「ファットコンマ」と発音されます)はコンマ演算子の 同義語ですが、もし左側の単語が文字か下線で始まっていて、かつ文字、数字、 下線でのみ構成されている場合、これを文字列として扱うという効果もあります。 これには他の場所では演算子、定数、v-文字列、関数呼び出しとして扱われる オペランドを含みます。 この振る舞いについて迷うことがあるなら、左オペランドを明示的に クォートすることも出来ます。 *1
=>
の左辺がidentifierっぽければ文字列として扱われるのが優先され、定数は展開されません。=>
の左辺に定数を使いたいときはこうする必要があります。
use strict; use warnings; use Data::Dumper; use constant HOGE_KEY => 'hoge'; print Dumper { HOGE_KEY() => 'fuga' };
これに限らず常に HOGE_KEY()
のように書くことを習慣付ける(あるいはlinterで検出する)のがいいのではないかと思ってきました。
そしてここまで書いて perldoc constant
にまさにこのケースについて言及されているのを発見しました。
自動的に裸の単語をクォートするコンテキストで定数を使うと (サブルーチン呼び出しの場合と同様)問題が起こります。 例えば、$hash{CONSTANT} とはできません; CONSTANT は文字列として 解釈されるからです。 裸の単語をクォートする機構を防ぐために $hash{CONSTANT()} や $hash{+CONSTANT} を使ってください。 同様に、the => 演算子は左側の裸の単語をクォートするので、 CONSTANT => 'value' ではなく CONSTANT() => 'value' とする (または単に大矢印の代わりにカンマを使う)必要があります。 *2
perldocにはなんでも書いてあります。