そういえば、日曜日は Perl 入学式に行ってきたのでした。

Perl 入学式は、1年かけて環境構築から Perl の文法や機能を学びつつ最終的に何かアプリを作るのを目指してる感じのイベント(とかだいたいそんな感じだよね?)です。で、僕は「サポーター」といって、大学の授業で言うところのTAみたいなやつをやってました。10数年ぶりですね。こういうの。

今回は、配列の詳細とハッシュとリファレンスという、なかなか難易度の高い分野でしたが、みなさんちゃんとついてきてるようでした。

学校とか会社とかでも、ちゃんとしたテキストがあって、サポーターなりTAなりメンターなりが、あれだけ沢山いる環境は無いから、本当に素晴らしいな、と思います。

資料はこのへんらしいです。

さてさて、今回サポーターやってて、参加者の皆さんが嵌ってたっぽい場所について、書いてみようかと思います。

コンテキスト

「配列をなんか操作して、表示」みたいなのは練習問題で何度か出てきたのですが、

my @array = ('aaa', 'bbb');
... #なんか操作して...
print "@array\n"; #配列の中身を表示

みたいに書くのですが、これを

print @array . "\n"; #配列の中身を表示

と書くと、

2

とか何故か数字が表示されて、「あれ?あれ?」ってなります。何故かというと、print のところで、文字列の連結をしているからです。文字列はスカラーなので、配列がスカラー扱いされます。 (これを「スカラーコンテキスト」といいます)。配列をスカラーコンテキストで取り扱う(「スカラーコンテキストで評価」するといいます)と、「配列の要素数」が返ります。そのため、数字が返ってしまうわけです。

正しいやり方は、(Perl なので、「正解はひとつ!じゃない!!」のですが)、最初のように、文字列の中に入れるとか、print に配列渡しする

print @array, "\n"; #文字列連結ではなく、カンマで区切って複数の引数を渡す

とか、join を使う

print join('', @array) . "\n"

とかそんなところですかね。(join は演習やってるタイミングでは未学習だったけど)

かくいう僕も、わりと最近コンテキストに嵌って「あれ?」ってなったので、ある程度慣れてもこれは油断ならないな、と思います。

split の使い方

文字列 "/usr/bin/env perl" という文字列を、スラッシュ ('/') で分割して配列に格納してみましょう

という演習問題のやつですね。

split /\//, "/usr/bin/env perl";

みたいな感じでエスケープする、というのが現時点の答えですが、「バックスラッシュ無しにできませんか?」ってやっぱ聞かれましたね。

僕は

split qr{/}, "/usr/bin/env perl";

って書くかなぁ。ほかのサポーターの人は m{}使うって言ってましたね。(デリミタは好みに応じて色々です。「!」使う人が多かったっぽい)まあそのどっちかですね。

vote.pl

今回の最後の問題は結構難しいやつで、僕も数分くらい「あれ?どうやるんだ?」と考え込んだようなやつでした。 僕が書いてみたのはこんな感じです。多分講師の papix さんが書いてたのとほとんど同じやつです。

#!/usr/bin/perl
use strict;
use warnings;
use utf8;
binmode STDOUT, ':utf8';
# vote.pl
# 1. 「自分の名前 (name)」と「好きな食べ物の配列のリファレンス (favorite\_foods)」を持ったハッシュリファレンスを作成しましょう (つまり、好きな食べ物は複数個書いてください)
# 2. 同様のハッシュリファレンスを2, 3個作ってみましょう (周りの人のリアルデータを使ってハッシュrefを作ると良いかもしれません)
# 3. 作成した複数のハッシュリファレンスを1つの配列に格納しましょう (配列を操作する関数を使っても良いですし、直で代入しても良いです)
# 4. どんな方法でも良いので、好きな食べ物のランキングを作って表示してみて下さい

my $hashref1 = {
    name           => 'tsucchi',
    favorite_foods => ['寿司', '刺身', '唐揚げ', 'ラーメン'],
};

my $hashref2 = {
    name           => 'シャーロック シェリンフォード',
    favorite_foods => ['かまぼこ', 'ラーメン'],
};

my $hashref3 = {
    name           => '名無しの 権兵衛',
    favorite_foods => ['ラーメン', 'うどん', 'そば', '二郎', '寿司'],
};

my @data = (
    $hashref1,
    $hashref2,
    $hashref3,
);

#use Data::Dumper; warn Dumper(\@data);

my %rank = ();

for my $datum ( @data ) {
    for my $food ( @{ $datum->{favorite_foods} } ) {
        $rank{$food}++;
    }
}

for my $food_name ( sort { $rank{$b} <=> $rank{$a} } keys %rank ) {
    print "$food_name : $rank{$food_name}\n";
}

これは

my %rank

を考えつくかどうか、%rank にどうやってデータを突っ込むかがポイントですね。初心者や、プログラミングの経験が少ない人には厳しいかもですね。 こればかりは沢山書いて慣れるしか無いと思います。

つーわけで、多分 YAPC の入学式でもサポーターやってる予定ですし、また機会があれば Perl 入学式にお邪魔したいなー、と思ってますのでよろしくです。