私が歌川です

@utgwkk が書いている

Perlの定数とfat comma

たぶん世界中のみなさまがハマったことあると思いますが、私も本日ハマりました。

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にはなんでも書いてあります。