Perlのハッシュや配列、そしてそれぞれのリファレンスを使って、データ構造を作る練習をしたいっていうときに、そのための例題というか練習問題みたいなものを作ってみる、というのは良い方法だと感じる。
たとえば配列なら、果物とか色とかを使うと作りやすい。
#!/usr/bin/env perl use strict; use warnings; use 5.014; my @fruits = qw(apple orange grape melon lemon strawberry banana); my $colors = [qw(red blue black green purple pink yellow)]; say $fruits[3]; #=> melon say $colors->[5]; #=> pink
とか何とか。
これがハッシュ系だと何だろうなあ、と思って、まあそれぞれの役割があるロックバンドとか、スポーツチームとか作りやすいのかな、と思う。
たとえばサッカーなら、エスパルスのMFは誰で、とかアルゼンチン代表のDFは誰で・・とか。サッカーの場合はレギュラー選手だけでも、同じポジションに複数の選手がいたりするから、ハッシュと配列の組み合わせなんか作るのに便利そうだ。
あるいはバンドなんかでも同じようなことは言える。ギターが二人いるバンドも少なくないし、スカパラみたいな大所帯バンドやクラシックのオーケストラまで対象を広げたらかなり大変なことになりそうだ。(いい意味で)
と言いつつ、ぼくはスポーツを熱心には見ないし、オーケストラの実情も知らなければ最近の音楽も知らないから、すぐに浮かぶ例題にできそうな人たちと言ったらとりあえずビートルズぐらいしかいない。
use DDP; my $beatles = { guitar => [qw(John George)], bass => 'Paul', drums => 'Ringo', }; p $beatles;
実行すると・・
\ { bass "Paul", drums "Ringo", guitar [ [0] "John", [1] "George" ] }
ギターの二人をさらにハッシュで強引に表現すると、こんなか?
my $beatles = { guitar => { vocal => 'John', leadguitar => 'Gerorge', }, bass => 'Paul', drums => 'Ringo', };
ダンプ(Dump。内部構造をレントゲン的に出力)すると・・
\ { bass "Paul", drums "Ringo", guitar { leadguitar "Gerorge", vocal "John" } }
ふむ。まあ、ジョージも歌いますけどね・・とりあえず便宜的に。
というかビートルズだけでもいくらでも楽しいデータ構造はできそうだ。
たとえば、ジョージがシタールも弾くことをどう表現するか? トカ。
あるいは何年に出たアルバムの何曲目がどんな曲で、それをどう取り出すか? トカ。
夢は広がる。
上記からもう少し進めて、最後に挙げたデータ構造からジョージの名前を取り出すにはどうしたらいいか。
ポクポクポク・・(古い)
say "His name is $beatles->{guitar}{leadguitar}.";
実行。
His name is Gerorge.
オーケー。では同じデータ構造から、リンゴの担当楽器を取り出すにはどうしたらいいか?
当然僕はその楽器を知っているが、便宜的に知らないことにして・・知らなかったらどう取り出すかというゲームです。
ポクポクポク・・(古い)
for (keys %$beatles) { if ($beatles->{$_} eq 'Ringo') { say "He plays $_."; } }
実行。
He plays drums.
なんかもっと全然スマートに書けそうですが・・というかプログラム以前に英語がすごいですが。
じゃ、ジョンの担当はなんでしょうか。
熟考・・たぶん上のをチャチャッと書き直せば良さそうだが。
for (keys %{$beatles->{guitar}}) { if ($beatles->{guitar}{$_} eq 'John') { say "His role is $_."; } }
実行。
His role is vocal.
ふむ。これもまあ英語の方が問題に思えますが、ヨシとしましょう。
じゃあじゃあ(ムキになって)、上記はハッシュリファレンス使ったけど、普通のハッシュで書き直したらどうなるか。
中身を書き換えるのは面倒なので、大元のビートルズだけ普通のハッシュにしましょう。
こんなですか。
my %beatles = ( guitar => { vocal => 'John', leadguitar => 'Gerorge', }, bass => 'Paul', drums => 'Ringo', );
ここから同じようにジョンの担当を出しましょう。
for (keys $beatles{guitar}) { if ($beatles{guitar}{$_} eq 'John') { say "His role is $_, again."; } } #=> His role is vocal, again.
ふむ。さっきのはコレなので・・
#再掲 for (keys %{$beatles->{guitar}}) { if ($beatles->{guitar}{$_} eq 'John') { say "His role is $_."; } }
ほっとんど変わらないですね。
だから思うんですけど、ことデータ構造について考える場合、リファレンスってたんに「てっとりばやくそれ(ハッシュや配列)を書ける」というだけのものだと考えていいんじゃないか、少なくとも初心者の場合、という気が今はしています。
リファレンスにはもう一個大きな特徴で、そうした多重構造をもったデータをスカラーとして持ち運べる&運んだ先での変更が元に影響をあたえる、とかあると思うんですが、やっぱりそれは当面分けて考えてもいいんじゃ・・とかってことをあらためてこのビートルズの皆さんの様子を見ながら思ったりもしました。
こんな風に、自分で自分に問題を作って、それを解いたりちょっとアレンジとかしたりするの、普通に面白いし、たしかに仕事みたいにヒリヒリしていないから、目が覚めるような突然の向上とかはないかもしれないけれど、何もやらないよりは成長の助けになっていると思うし、単純に楽しい。それが趣味プログラミングの良さで、こんな風にして日々の仕事でダメージを受けたりささくれだったりした何かをなめしている、という気もします。