ROUTE 3390

備忘録的な用途で書いていますが、どなたかの役に立つ事があれば嬉しいです。

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

以上、普段はそんなに意識しないし、困る事もそんなに無い事でしたー。