読者です 読者をやめる 読者になる 読者になる

ゆーすけべー日記

はてなBlogってどーなの!?

データ表現についてわかった瞬間

Web Essay Perl

データの表現と操作

Webサービス等に必要な言語取得についてです。 プログラミング言語を勉強しようという時にデータの表現方法を把握した瞬間に、 「パッ」とその言語に対する理解が明るくなった気がします。

プログラミングは、抽象的に言えば、目的を果たすために「データ」を「操作する」プログラムを書く行為と呼べるでしょう。 例えば二つの数字を足し算するプログラムを考えてみます。これは「4+3=7」などを機械的に行ってくれるものです。 プログラム内の流れはこのようになるでしょう。

  1. 二つの数字を受け取り、それぞれデータとして保持する
  2. 二つのデータを足し算して結果というデータに入れる
  3. 結果を出力する

実例を見た方が早いと思います。 この足し算プログラムをエラー処理とかすっ飛ばして分かりやすいPerlのコードにするとこのようになります。

use strict; #おまじない
use warnings; #おまじない

my $number1 = $ARGV[0]; #第1引数を変数に入れる
my $number2 = $ARGV[1]; #第2引数を変数に入れる
my $result  = $number1 + $number2;  #結果に入れる
print "Result: $result\n";

「sum.pl」などのファイル名で保存して、ターミナルから以下のように実行します。

$ sum.pl 4 3

Result: 7 」という文字列がターミナルに出力されたはずです。 ここで出てきた「 $number1」「 $number2 」「 $result 」というのが、 Perlにおいてスカラーと呼ばれるデータを表す変数になります。 スカラー とはようは数字だったり文字だったりして「4という数字なら4だけだよ」と単一データを表せます。 ここまでの理解はそう難しくないはずです。

配列とハッシュ

Perlで言うスカラーを理解したら、次は 配列とハッシュ について把握しようというのが定石です。 配列なら配列のみ、ハッシュならハッシュのみを表現する分にはこれも結構簡単です。

僕の好きな食べ物を適当に列挙するとしましょう。配列を使って以下のように表現できます。

my @foods = ( 'ラーメン', '寿司', 'カレー', 'スパゲッティ', 'ステーキ' );

@foodsってのには頭から

  • ラーメン
  • 寿司
  • カレー
  • スパゲッティ
  • ステーキ

が入っています。先頭のラーメンを取得したければ「 $foods[0] 」と表現すればよいでしょう。 中に入っている5つの文字列を順番に処理したければこのような「配列の操作」方法があります。

for my $food (@food) {
    print "I like $food\n";
}

他にも配列にまつわる操作はいくつかあるので基本を押さえておいた方がよいでしょう。

では、他の言語では連想配列とも呼ばれるハッシュについてです。 これは「 キーとバリュー 」で構成されるものと覚えておくとよいでしょう。 配列の場合、個々の要素にアクセスしたければ「 $foods[0] 」の「0」のように 数字 で指定をしていました。 数字というのは配列の場合は往々にして0から始まり、1づつ加算されていく順番を意味します。 ではハッシュってのはどうかと言うと数字を使うのじゃなくて任意の文字列を使うのです。 それがキーと今僕が呼んでいるものです。

人には名前がついていて、身長や体重という基本データがあります。 そこからハッシュについて発想すると分かりやすいです。 例えば僕の場合は名前というキーに対して「和田裕介」というバリューを持っています。 また身長というキーに対しては「172cm」というバリューを持っているという具合です。 これをPerlで表現するとこうなります。

my %ore = ( name => '和田裕介', tall => 172 );

「name」キーの値にアクセスするためには「 $ore{name} 」とします。 配列と同様ハッシュを操作するための関数もありますので、そちらもチェックです。

組み合わせて表現する

さて、次のステップが結構はまりどころ。僕がそうでした。 上記の名前と身長のキーを持つ人が複数名いたとします。複数名いると列挙して配列として表現したいところです。 つまり、テキストで頑張って表すと

最初の人(名前: Kさん、身長: 160cm)、2番目の人(名前: Yさん、身長: 182cm)、 3番目の人(名前: Tさん、身長: 148cm)...

という意味を持つデータの表現をプログラムでどうするか。 お気づきかと思いますが配列の中にハッシュをぶち込めばよいのです。 ただ、Perlの場合には注意点があって、配列やハッシュを組み合わせたデータを表現するには、 リファレンスというのをうまく使わないと表現しきれないのです。

my @people = (
    { name => 'Kさん', tall => 160 },
    { name => 'Yさん', tall => 182 },
    { name => 'Tさん', tall => 148 }
);

細かい解説は省きますが「 @people 」配列内の「{ name => 'Kさん', tall => '160' }」というのが、 一つのハッシュの無名リファレンスを表しています。 2番目のYさんの身長を取り出すためには「 $people[1]->{tall} 」と表現します。 リファレンスの場合、値の取り出し方が単なるハッシュとは違うので注意が必要で、 この辺りを理解するのが当初の僕にとって大変だったのです。

配列にもリファレンス表現があって、 ハッシュのリファレンスとも組み合わせたりするとかなり複雑なデータ構造を表現できます。 例えば、上記の人が3人出てくる例をもう一度使いましょう。 それぞれが複数の好きな食べ物を持っているということを表したかったらこのようにします。

my @people = (
    { name => 'Kさん', foods => [ 'カレー', 'ラーメン' ] },
    { name  => 'Yさん', foods => [ 'ハンバーガー', '牛丼', 'チキン' ] },
    { name => 'Tさん', foods => [ 'サラダ' ] }
);

通常の配列は「 () 」で表現していたものを今回は「 [] 」を使って配列の無名リファレンスとしました。 ちなみに、この「 @people 」配列からみんなの好きな食べ物を一覧で出力するには以下のような操作をします。

for my $person (@people) {
    for my $food ( @{ $person->{foods} } ) {
        print "$person->{name} likes $food!!\n";
    }
}

実行結果が結構面白いです。

Kさん likes カレー!!
Kさん likes ラーメン!!
Yさん likes ハンバーガー!!
Yさん likes 牛丼!!
Yさん likes チキン!!
Tさん likes サラダ!!

スカラー、配列、ハッシュで表現する

実はこれまで解説してきた、スカラー、配列、ハッシュ。Perlの場合だとそれぞれのリファレンス。 これさえ把握してしまえば、「友達の好きな食べ物」とかもわりと複雑なことでも表現できてしまうわけです。 オブジェクト指向が少しでも分かる人ならば、「人クラス」を作るという方法もあると思うかもしれませんが、 場合によってはクラスを作ることでクラス定義が必要だったり生成コストとかも考えると、 ハッシュや配列だけで十分なケースもあります。 特に最初の言語に対する入門時には、 こうした言語にとってのプリミティブなデータ表現方法をまずは習得すると「パッ」と理解が開けるかもしれません。