Perlで不思議なハッシュが作れるはなし
このエントリーを書いたキッカケはこのtogetterです。
実際に書いて調べて、リストと配列は別物であるとか勉強になりました。
なかでもハッシュのキーに「リスト(配列ではない)」を指定した時の動作は面白かったので、私の検証結果をまとめてみました。
まずは普通のハッシュを作ってDumperで表示します。
use 5.010; use Data::Dumper my %hash; $hash{xyz} = 'hoge'; say Dumper \%hash;
するとこうなります。
$VAR1 = { 'xyz' => 'hoge', };
では少し追記して、ハッシュのkeyにリストコンテキストを指定して、値にfugaを入れます。
use 5.010; use Data::Dumper my %hash; $hash{xyz} = 'hoge'; $hash{qw/x y z/} = 'fuga'; say Dumper \%hash;
するとどうなるでしょう?
$VAR1 = { 'xyz' => 'hoge', 'xyz' => 'fuga', };
ナニコレーーーーーーーーーー!!!!
なんと、keyが重複しているではあーりませんか!
いやいやいや、落ち着いて考えよう。
んなわけないでしょ。
値を取り出してみよう。ってやったらこうなりました。
say $hash{xyz}; # hoge say $hash{qw/x y z/}; #fuga say scalar keys %hash; # 2
ほほーー、やはり2セット存在していて
しっかりとkeyを区別しているようだ。
改めてDumpを見てみる。。
$VAR1 = { 'xyz' => 'hoge', 'xyz' => 'fuga', };
、、、、しっかし不思議なハッシュだなー
Dumpすると同じように見えるけど、実際は何か違うんだよね。きっとね。
じゃあ実際、何が違うのか調べてみる。
use 5.010; use Data::Dumper my %hash; $hash{xyz} = 'hoge'; $hash{qw/x y z/} = 'fuga'; say Dumper \%hash; for my $key ( keys %hash ) { $key =~ s/([^\w])/unpack('H2', $1)/eg; say $key; }
ハッシュのkeyをURLエンコードする時のようにしてみます。
(正規表現で半角数字と半角アルファベット以外を変換しています)
$VAR1 = { 'xyz' => 'hoge', 'xyz' => 'fuga', }; xyz x1cy1cz
お、リストで指定したkeyは文字の間に「1c」というのが挟まっていますね。
ASCIIコードについて書かれているページを参考にするとHexで1cはFile separatorを表すそうです。
まぁようするに、バイトコードレベルでは違うkeyだったから、パッと見た感じ
不思議に見えたハッシュですが、とくに不思議でもなんでも無かったという事でした。
下記はFile separatorについて少し。
use 5.010; my @array = qw/x y z/; say @array;
これはリストコンテキストを配列変数に格納しています。
その配列変数を表示するとこのようになります。
xyz
これはxyzがただjoinされたのではなく、
File separatorによって1つの文字列となっています。
さっきの「1c」ですね。
PerlはFile separatorを「$,」ダラーカンマという特殊変数に格納しています。
というわけで、下記のような事が出来ます。
use 5.010; $, = '---'; my @array = qw/x y z/; say @array;
するとこのように表示されます。
x---y---z
以上、普段はそんなに意識しないし、困る事もそんなに無い事でしたー。