ハッシュをスカラーコンテキストで評価したものの正体。

正体のわからぬ物を発見。ある種UMAですUMA

何かと言いますとid:hirataraさんのハッシュの判定は裸でを見てたら何か見慣れぬものを発見。

disp    : 1/8

↑ここ。

ちなみに

$hoge{abc} = 'def';
printf("disp    : %s\n", scalar(%hoge));

↑この結果です。

気になって調べたら近藤嘉雪先生にぶつかりました。
http://www.context.co.jp/perlnews/bn/perl-newsletter-0008.html

◇ハッシュをスカラーコンテキストで評価する

ハッシュをスカラーコンテキストで評価すると何が得られるでしょうか?
以前に説明しましたが、配列の場合はスカラーコンテキストで評価すると要素の個数が得られます。
このことから類推すると、ハッシュをスカラーコンテキストで評価すると、ハッシュの要素の個数が得られそうな気がします。
しかし、そうは問屋が卸さないのが、Perlの面白い(?)ところです。

ハッシュをスカラーコンテキストで評価すると、"103/128"のような文字列が得られます。
この文字列はハッシュの内部の状態を示すものですが、スクリプトを書く上でこの情報を利用する機会はほとんどありません。

ちなみにこの値は、ハッシュ表のエントリ(バケットといいます)の使用状況を示しています。
2番目の数字は用意したエントリの総数、1番目の数字はそのうち使用中のエントリの個数を表します。
繰り返しになりますが、これらの値は意味を覚えなくて構いません。


とのことで「意味を覚えなくて構いません。」と言われても気になって調べてみたけどやっぱりよくわかんなかった話。

ちょっとした実験

$ perl -e "my %hash = (1..1); warn scalar %hash;"
1/8 at -e line 1.
$ perl -e "my %hash = (1..2); warn scalar %hash;"
1/8 at -e line 1.
$ perl -e "my %hash = (1..3); warn scalar %hash;"
2/8 at -e line 1.
$ perl -e "my %hash = (1..4); warn scalar %hash;"
2/8 at -e line 1.
$ perl -e "my %hash = (1..5); warn scalar %hash;"
3/8 at -e line 1.
$ perl -e "my %hash = (1..6); warn scalar %hash;"
3/8 at -e line 1.
$ perl -e "my %hash = (1..7); warn scalar %hash;"
4/8 at -e line 1.
$ perl -e "my %hash = (1..8); warn scalar %hash;"
4/8 at -e line 1.

としてみて「あぁ要はkeyの数なのね。」とか浅はかな考えを持ったらば、

9以降様子が変わりました。

$ perl -e "my %hash = (1..9); warn scalar %hash;"
4/8 at -e line 1.
$ perl -e "my %hash = (1..10); warn scalar %hash;"
4/8 at -e line 1.
$ perl -e "my %hash = (1..11); warn scalar %hash;"
4/8 at -e line 1.
$ perl -e "my %hash = (1..12); warn scalar %hash;"
4/8 at -e line 1.

増えなくなったぞ。。

なぞを探るべく

↓のようなものを作成。変わったら出力してくれます。

use strict;

my $before_res = '';

for my $i (1..500) {
    my %hash = (1..$i);
    my $res = scalar %hash;
    if ($before_res ne $res) {
        $before_res = $res;
        print "count: $i, value: $res";
    }
}


で、結果

ビャーッと出てますがご辛抱を。

$ perl -l scalar_hash.pl
count: 1, value: 1/8
count: 3, value: 2/8
count: 5, value: 3/8
count: 7, value: 4/8
count: 169, value: 9/16
count: 170, value: 17/32
count: 171, value: 61/128
count: 173, value: 62/128
count: 179, value: 63/128
count: 183, value: 64/128
count: 187, value: 65/128
count: 189, value: 66/128
count: 197, value: 67/128
count: 199, value: 68/128
count: 201, value: 69/128
count: 203, value: 70/128
count: 205, value: 71/128
count: 207, value: 72/128
count: 209, value: 73/128
count: 211, value: 74/128
count: 213, value: 75/128
count: 215, value: 76/128
count: 217, value: 77/128
count: 219, value: 78/128
count: 221, value: 79/128
count: 223, value: 80/128
count: 225, value: 81/128
count: 227, value: 82/128
count: 229, value: 83/128
count: 231, value: 84/128
count: 233, value: 85/128
count: 235, value: 86/128
count: 237, value: 87/128
count: 239, value: 88/128
count: 243, value: 89/128
count: 245, value: 90/128
count: 247, value: 91/128
count: 249, value: 92/128
count: 253, value: 93/128
count: 255, value: 114/256
count: 257, value: 115/256
count: 259, value: 116/256
count: 261, value: 117/256
count: 263, value: 118/256
count: 265, value: 119/256
count: 267, value: 120/256
count: 269, value: 121/256
count: 271, value: 122/256
count: 273, value: 123/256
count: 275, value: 124/256
count: 279, value: 125/256
count: 281, value: 126/256
count: 283, value: 127/256
count: 285, value: 128/256
count: 289, value: 129/256
count: 291, value: 130/256
count: 293, value: 131/256
count: 299, value: 132/256
count: 301, value: 133/256
count: 303, value: 134/256
count: 305, value: 135/256
count: 311, value: 136/256
count: 313, value: 137/256
count: 315, value: 138/256
count: 321, value: 139/256
count: 323, value: 140/256
count: 325, value: 141/256
count: 331, value: 142/256
count: 341, value: 143/256
count: 349, value: 144/256
count: 351, value: 145/256
count: 359, value: 146/256
count: 361, value: 147/256
count: 367, value: 148/256
count: 369, value: 149/256
count: 371, value: 150/256
count: 377, value: 151/256
count: 379, value: 152/256
count: 381, value: 153/256
count: 385, value: 154/256
count: 387, value: 155/256
count: 389, value: 156/256
count: 391, value: 157/256
count: 395, value: 158/256
count: 397, value: 159/256
count: 399, value: 160/256
count: 401, value: 161/256
count: 403, value: 162/256
count: 405, value: 163/256
count: 411, value: 164/256
count: 413, value: 165/256
count: 415, value: 166/256
count: 421, value: 167/256
count: 423, value: 168/256
count: 425, value: 169/256
count: 431, value: 170/256
count: 433, value: 171/256
count: 435, value: 172/256
count: 441, value: 173/256
count: 443, value: 174/256
count: 445, value: 175/256
count: 447, value: 176/256
count: 451, value: 177/256
count: 455, value: 178/256
count: 461, value: 179/256
count: 465, value: 180/256
count: 491, value: 181/256
count: 493, value: 182/256
count: 495, value: 183/256
count: 497, value: 184/256
count: 499, value: 185/256

何か規則性が見えて来ませんか?

要素が少ない時は値が変わらずでかくなってくると都度変わってますな。

今の脳みそで思いつく事
少ない時はあらかじめ確保?
もしくは領域内でやりくりしてる?
でかくなると都度やってんの?
そもそもバケットって何だ?

というわけで?だらけです。

まとめ

というわけでとりあえずは1年後の自分に託したいと思います。