Perlのリファレンスを学ぶ

Oct 4, 2008   #Perl  #Programming  :

はじめに

すぐわかる オブジェクト指向 Perl』を読んでいます。CやGaucheとの関連から結構、頭に入ってきやすいです。自分用の備忘録として書いておきます。

主な違い

Perlのリファレンスというのは、Cのポインタのこと。主な違いは:

  1. C言語のポインタは、メモリーアドレスがダイレクトに入っている。
  2. ある文字列の1文字目をC言語のポインタで指し、ポインタに1加算すると、ポインタは2文字目を指す。同様に、ある配列の1要素目を指しているポインタに1を加算すると2要素目を指す。このようにポインタの中身を自由に計算できる。
  3. ポインタを使うときは、コンピュータのどのメモリーをどのぐらい使うかあらかじめ計算しておく必要がある。
  4. ポインタに意味のない値をうっかり入れてしまったり、不適切な演算を行ったりすると、プラグラムが馬鹿正直にそのメモリ空間を指すので暴走してしまう。
  5. コンピュータ上ではプログラム自身もデータである。ポインタ演算の失敗によって、メモリー上の他のプログラムやOSも書き換えられてしまうことによって軒並み暴走が起こる可能性がある。


スカラー変数のリファレンス

Perlの場合
use strict;
use warnings;
my $age = 26;
my $ref_age = \$age;
print($$ref_age, "\n");
Cの場合
#include <stdio.h>
int main(int argc, char *argv[])
{
int age = 26;
int *ref_age =
printf("%3d\n", *ref_age);
return ;
}

配列のリファレンス

Perlの場合
use strict;
use warnings;
my @month = (
'January', 'February', 'March',     'April',   'May',      'June',
'July',    'August',   'September', 'October', 'November', 'December'
);
# $ref_monthに@monthのリファレンスを代入
my $ref_month = \@month;
# 配列のデリファレンス
print(@$ref_month, "\n");
print($$ref_month[1], "\n");
# $$ref_month[4]のシンタックスシュガー
print($ref_month->[4], "\n");
Cの場合

char型の二次元配列をポインタでしか宣言できなかった(..;)だから、上のPerlとはちょっと違う。

#include <stdio.h>
int main(int argc, char *argv[])
{
char *month[] = {
"January", "Feburary", "March", "April", "May",
"June", "July", "August", "September", "October",
"November", "December"
};
printf("%s\n", month[1]);
printf("%s\n", month[4]);
return ;
}

二次元配列

つぎのようにして、二次元配列を使うことができる。

use strict;
use warnings;
my @jan = ('January', 31);
my @feb = ('Feburary', 28);
my @mar = ('March', 31);
my @apr = ('April', 30);
my @may = ('May', 31);
my @jun = ('June', 30);
my @jul = ('July', 31);
my @aug = ('August', 31);
my @sep = ('September', 30);
my @oct = ('October', 31);
my @nov = ('November', 30);
my @dec = ('December', 31);
my @month = (\@jan, \@feb, \@mar, \@apr, \@may, \@jun, \@jul,
\@aug, \@sep, \@oct, \@nov, \@dec);
foreach my $x (@month) {
print($x->[], "\n");
}

また、Lispのlambdaみたいな無名の手続きならぬ、無名の配列を作ることができる。

use strict;
use warnings;
my @month = (
[ 'January',   31 ],
[ 'Feburary',  28 ],
[ 'March',     31 ],
[ 'April',     30 ],
[ 'May',       31 ],
[ 'June',      30 ],
[ 'July',      31 ],
[ 'August',    31 ],
[ 'September', 30 ],
[ 'October',   31 ],
[ 'November',  30 ],
[ 'December',  31 ],
);
foreach my $x (@month) {
print($x->[], ": ");
print($x->[1], "\n");
}

ハッシュのリファレンス

use strict;
use warnings;
# ハッシュの宣言
my %month = (
January   => 31,
Feburary  => 28,
March     => 31,
April     => 30,
May       => 31,
June      => 30,
July      => 31,
August    => 31,
September => 30,
October   => 31,
November  => 30,
December  => 31,
);
# ハッシュの要素を表示
print($month{January}, "\n");
# ハッシュのキーを表示する
print(keys %month, "\n");
# ハッシュのリファレンス
my $ref_month = \%month;
# リファレンスのデリファレンス
print(keys %$ref_month, "\n");
# リファレンスから要素を得る
print($$ref_month{January}, "\n");
# リファレンスから要素を得る(シンタックスシュガー)
print($ref_month->{January}, "\n");

無名ハッシュ

use strict;
use warnings;
# ハッシュの宣言
my $ref_month = {
January   => 31,
Feburary  => 28,
March     => 31,
April     => 30,
May       => 31,
June      => 30,
July      => 31,
August    => 31,
September => 30,
October   => 31,
November  => 30,
December  => 31,
};
# リファレンスのデリファレンス
print(keys %$ref_month, "\n");
# リファレンスから要素を得る
print($ref_month->{January}, "\n");

関数のリファレンス

use strict;
use warnings;
my $ref_sub = \
my $result = $ref_sub->(1, 2);
print($result, "\n");
exit;
sub add {
my ($x, $y) = @_;
return ($x + $y);
}

無名関数

これこそlambdaと同じだよ!

use strict;
use warnings;
my $ref_sub = sub {
my ( $x, $y ) = @_;
return ( $x + $y );
};
my $result = $ref_sub->(1, 2);
print($result, "\n");
exit;