Perl 6を見よう見まねで遊んているところを世間に発表するコーナーです。基本『かんたんPerl』の流れに沿って、Perl 5ではこうだったのがPerl 6ではどうなった、という形式で考察しています。てなことで今日はハッシュについて研究します。


配列は、順番をキーにランダムアクセスできるデータでした。Perl 5で配列を使ったプログラムの一例はこうなります。
これは、月の順番を引数に得て、その月の英語名(略称)を返します。
これは、月が1月から12月という順番を持つデータだからです。配列はゼロ始まりですが、ゼロ月という月はないので、先頭にDUMMYというデータを入れています。
一方、ハッシュは、文字列を使って別の文字列を検索できるデータです。連想配列といいます。検索に使うデータをキー、キーによって検索されるデータを値と言います。
ということで、ハッシュのプログラムの一例として、月名を引数に得て月数を返すプログラムを考えます。Perl5ではこうなります。
このように、%monthというハッシュは%というシジルを持つが、それを検索する$hash{$nam}という式は$で始め(スカラーだから)、検索するキーはブレース{}で囲みます。
ハッシュは順番が関係ないのでDUMMYは取りました。
さて、これをこのままPerl 6に移植するとこうなります。
まず、代入文の右辺のリストの()を付けなくても良くなりました。
次に、%monthというハッシュを検索する式もシジルは%のまま、%month{$nam};と書けば良くなりました。
これはもう配列の回に見ましたね。
ところで、こう書くとエラーになります。
{}の中にベアワードを書くと「定義されていない名前」と怒られます。これはコンパイルエラーです。こう書きます。
あるいはこうでもいいです。
ここで<Dec>は前回でてきた、qw演算子の代わりになるもので、引用符を付けます。
逆に変数で検索するときに%month<$nam>のように書くと、それは%month{'$nam'}と書くのと一緒だから、そんなキーの値はありませんと実行時エラーが返ります。
(「$nam月」というハッシュ要素を作っていれば別ですが。。)
ということで、変数で検索する時とリテラルで検索するときで式が変わります。これはちょっとややこしいですね。
ハッシュのキーを取り出すにはkeysメソッドを使います。
月の一覧を表示していますが、早い順でも、アルファベット順でもありません。これは順不同です。アルファベット順にソートしてみます。
月名でソートしてもいまいち意味がありませんが、Perl 5だったら
と書いたところを、オブジェクト指向のPerl 6では
となるところが面白いですね。%monthの、keysを取って、sortするということで、日本人にはこの方が分かりやすいような気がします。
#! /usr/local/bin/perl
# arrP5.pl -- Perl 5で配列操作
use strict;
use warnings;
use 5.10.0;
my $num = shift;
my @month = qw (DUMMY Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
say "The month No. $num is $month[$num]";
# arrP5.pl -- Perl 5で配列操作
use strict;
use warnings;
use 5.10.0;
my $num = shift;
my @month = qw (DUMMY Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
say "The month No. $num is $month[$num]";
これは、月の順番を引数に得て、その月の英語名(略称)を返します。
[sample]$ ./arrP5.pl 3
The month No. 3 is Mar
The month No. 3 is Mar
これは、月が1月から12月という順番を持つデータだからです。配列はゼロ始まりですが、ゼロ月という月はないので、先頭にDUMMYというデータを入れています。
一方、ハッシュは、文字列を使って別の文字列を検索できるデータです。連想配列といいます。検索に使うデータをキー、キーによって検索されるデータを値と言います。
ということで、ハッシュのプログラムの一例として、月名を引数に得て月数を返すプログラムを考えます。Perl5ではこうなります。
#! /usr/local/bin/perl
# hashP5.pl -- Perl 5でハッシュ操作
use strict;
use warnings;
use 5.10.0;
my $nam = shift;
my %month = (
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
);
say "The month named $nam is $month{$nam}";
# hashP5.pl -- Perl 5でハッシュ操作
use strict;
use warnings;
use 5.10.0;
my $nam = shift;
my %month = (
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
);
say "The month named $nam is $month{$nam}";
[sample]$ ./hashP5.pl Apr
The month named Apr is 4
The month named Apr is 4
このように、%monthというハッシュは%というシジルを持つが、それを検索する$hash{$nam}という式は$で始め(スカラーだから)、検索するキーはブレース{}で囲みます。
ハッシュは順番が関係ないのでDUMMYは取りました。
さて、これをこのままPerl 6に移植するとこうなります。
#! /usr/bin/env perl6
# hashP6.p6 -- Perl 6でハッシュ操作
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
"The month named $nam is %month{$nam}".say;
}
# hashP6.p6 -- Perl 6でハッシュ操作
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
"The month named $nam is %month{$nam}".say;
}
[sample]$ ./hashP6.p6 May
The month named May is 5
The month named May is 5
まず、代入文の右辺のリストの()を付けなくても良くなりました。
次に、%monthというハッシュを検索する式もシジルは%のまま、%month{$nam};と書けば良くなりました。
これはもう配列の回に見ましたね。
ところで、こう書くとエラーになります。
#! /usr/bin/env perl6
# hashP6_2.p6 -- Perl 6でハッシュ操作2(エラー
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
"The month named $nam is %month{$nam}".say;
"BTW, the month named Dec is %month{Dec}".say;
}
# hashP6_2.p6 -- Perl 6でハッシュ操作2(エラー
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
"The month named $nam is %month{$nam}".say;
"BTW, the month named Dec is %month{Dec}".say;
}
[sample]$ ./hashP6_2.p6 Jun
===SORRY!=== Error while compiling /Users/query1000/Dropbox/kpc/sample/./hashP6_2.p6
Undeclared name:
Dec used at line 22
===SORRY!=== Error while compiling /Users/query1000/Dropbox/kpc/sample/./hashP6_2.p6
Undeclared name:
Dec used at line 22
{}の中にベアワードを書くと「定義されていない名前」と怒られます。これはコンパイルエラーです。こう書きます。
#! /usr/bin/env perl6
# hashP6_3.p6 -- Perl 6でハッシュ操作2(修正
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
"The month named $nam is %month{$nam}".say;
"BTW, the month named Dec is %month{'Dec'}".say;
}
# hashP6_3.p6 -- Perl 6でハッシュ操作2(修正
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
"The month named $nam is %month{$nam}".say;
"BTW, the month named Dec is %month{'Dec'}".say;
}
[sample]$ ./hashP6_3.p6 Jul
The month named Jul is 7
BTW, the month named Dec is 12
The month named Jul is 7
BTW, the month named Dec is 12
あるいはこうでもいいです。
#! /usr/bin/env perl6
# hashP6_4.p6 -- Perl 6でハッシュ操作3(修正2
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
"The month named $nam is %month{$nam}".say;
"BTW, the month named Dec is %month<Dec>".say;
}
# hashP6_4.p6 -- Perl 6でハッシュ操作3(修正2
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
"The month named $nam is %month{$nam}".say;
"BTW, the month named Dec is %month<Dec>".say;
}
[sample]$ ./hashP6_4.p6 Aug
The month named Aug is 8
BTW, the month named Dec is 12
The month named Aug is 8
BTW, the month named Dec is 12
ここで<Dec>は前回でてきた、qw演算子の代わりになるもので、引用符を付けます。
逆に変数で検索するときに%month<$nam>のように書くと、それは%month{'$nam'}と書くのと一緒だから、そんなキーの値はありませんと実行時エラーが返ります。
(「$nam月」というハッシュ要素を作っていれば別ですが。。)
ということで、変数で検索する時とリテラルで検索するときで式が変わります。これはちょっとややこしいですね。
ハッシュのキーを取り出すにはkeysメソッドを使います。
#! /usr/bin/env perl6
# hashP6_5.p6 -- Perl 6でハッシュ操作5
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
my @mnames = %month.keys;
"The month named $nam is %month{$nam}".say;
"BTW, the month names are {@mnames}".say;
"and their numbers are %month{@mnames}".say; # ハッシュ スライス
}
# hashP6_5.p6 -- Perl 6でハッシュ操作5
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
my @mnames = %month.keys;
"The month named $nam is %month{$nam}".say;
"BTW, the month names are {@mnames}".say;
"and their numbers are %month{@mnames}".say; # ハッシュ スライス
}
[sample]$ ./hashP6_5.p6 Sep
The month named Sep is 9
BTW, the month names are Nov Jun Mar Jan Dec Aug Oct Sep Jul May Apr Feb
and their numbers are 11 6 3 1 12 8 10 9 7 5 4 2
The month named Sep is 9
BTW, the month names are Nov Jun Mar Jan Dec Aug Oct Sep Jul May Apr Feb
and their numbers are 11 6 3 1 12 8 10 9 7 5 4 2
月の一覧を表示していますが、早い順でも、アルファベット順でもありません。これは順不同です。アルファベット順にソートしてみます。
#! /usr/bin/env perl6
# hashP6_6.p6 -- Perl 6でハッシュ操作6
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
my @mnames = %month.keys.sort;
"The month named $nam is %month{$nam}".say;
"BTW, the month names are {@mnames}".say;
"and their numbers are %month{@mnames}".say; # ハッシュ スライス
}
# hashP6_6.p6 -- Perl 6でハッシュ操作6
sub MAIN (Str $nam) {
my %month =
Jan => 1,
Feb => 2,
Mar => 3,
Apr => 4,
May => 5,
Jun => 6,
Jul => 7,
Aug => 8,
Sep => 9,
Oct => 10,
Nov => 11,
Dec => 12,
;
my @mnames = %month.keys.sort;
"The month named $nam is %month{$nam}".say;
"BTW, the month names are {@mnames}".say;
"and their numbers are %month{@mnames}".say; # ハッシュ スライス
}
[sample]$ ./hashP6_6.p6 Oct
The month named Oct is 10
BTW, the month names are Apr Aug Dec Feb Jan Jul Jun Mar May Nov Oct Sep
and their numbers are 4 8 12 2 1 7 6 3 5 11 10 9
The month named Oct is 10
BTW, the month names are Apr Aug Dec Feb Jan Jul Jun Mar May Nov Oct Sep
and their numbers are 4 8 12 2 1 7 6 3 5 11 10 9
月名でソートしてもいまいち意味がありませんが、Perl 5だったら
@mnames = sort keys %months;
と書いたところを、オブジェクト指向のPerl 6では
my @mnames = %month.keys.sort;
となるところが面白いですね。%monthの、keysを取って、sortするということで、日本人にはこの方が分かりやすいような気がします。