Perlの哲学 - Perlに対する誤解を解く

Perlは値と参照を明確に区別する

Perlは、動的プログラミング言語ではめずらしく、値と参照を明確に区別することができるプログラミング言語です。

C言語をソフトウェアの基礎で学んでいるなら、値と参照の区別をすることは、比較的簡単です。

C言語の値とポインタに当たるものが、Perlにおける値と参照です。参照は、リファレンスとも呼ばれます。

まず前提として覚えておいてほしいことを先に書きます。

動的配列と連想配列

Perlは、言語に動的配列と、連想配列が組み込まれています。Perl言語では、動的配列は、単に配列、連想配列は、ハッシュと呼ばれます。

# 配列(動的配列)
my @nums = (1, 2, 3);

# ハッシュ(連想配列)
my %person = (age => 12, name => 'kimoto');

Perlで、覚えておいてほしいことは、配列とハッシュを代入できる変数は、特別な記号「@」「%」で、表現されるということです。

「@」はArrayの頭文字aに似ていると覚えましょう。「%」は、キーと値が対応しているように見えると覚えましょう。

数値や文字列を代入する変数は「$」で表現されます。

# 数値や文字列
my $num = 4;
my $name = 'kimoto';

変数の対応

変数の対応を簡単に書いておきます。

数値や文字列$num, $name
配列(動的配列)@nums
ハッシュ(連想配列)%person

Perlのデフォルトの代入は値のコピー

Perlは、C言語の文法を参考にしいてて、C言語を学んだ人が、学びやすい用に、配慮されています。

C言語における代入のデフォルトの動作は、値のコピーです。Perlもこれと同じ仕様になっています。

数値のコピー

数値をコピーしてみましょう。

my $num1 = 1;

# 数値のコピー
my $num2 = $num2;

1という値がコピーされます。びっくりしましたか? びっくりしませんね。C言語の言語仕様を知っている方にとっては、おなじみの動作です。

文字列のコピー

文字列をコピーしてみましょう。

my $name1 = 'kimoto';

# 文字列のコピー
my $name2 = $name1;

さて、何が起こるでしょうか。実は、文字列は、コピーされます。 $name1を変更したとしても、$name2の値は変わりません。

文字列を代入したときに、コピーが行われるということが、Perlの言語仕様です。文字列を安全に、渡すことができます。

内部実装は、コピーオンライトです。パフォーマンスは非常によく、シングルスレッド上であれば、競合の問題も起こりません。

配列のコピー

配列をコピーしてみましょう。

my @nums1 = (1, 2, 3);

# 配列のコピー
my @nums2 = @nums1;

さて何が起こるでしょうか。配列自体が、コピーされます。@num1の要素の値を変えたとしても、@nums2の要素は変わりません。

配列を代入したときに、コピーが行われるということが、Perlの言語仕様です。

ハッシュのコピー

ハッシュをコピーしてみましょう。

my %person1 = (age => 12, name => 'kimoto');

# ハッシュのコピー
my %person2 = %person1;

さて何が起こるでしょうか。ハッシュ自体が、コピーされます。%person1の要素の値を変えたとしても、%person2の要素は変わりません。

ハッシュを代入したときに、コピーが行われるということが、Perlの言語仕様です。

Perlの代入のデフォルトの動作は、すべてコピー

Perlの代入のデフォルトの動作は、すべてコピーです。

これはつまり、コピー用の関数を使わなくても、言語仕様の機能だけで、基本データ構造をコピーできることを意味しています。

値のコピーは、非常によく使う機能です。Perlは、言語仕様で、値のコピーができるのです。

Perlのデフォルトの

まずPerlは、値と参照を明確に区別するということを覚えておきましょう。

値は値そのものがコピーされ、参照においては、アドレスがコピーされます。

Perlは参照というデータ構造を持つ

Perlは、C言語のポインタと同じように参照を作ることができます。参照というのは、矢印をイメージしてもらうのがよいです。

# 数値の参照
my $num = 1;
my $num_ref = \$num;

# 文字列の参照
my $name = 'kimoto';
my $name_ref = \$name;

# 配列の参照
my @nums = (1, 2, 3);
my $nums_ref = \@nums;

# ハッシュの参照
my %person = (age => 1, name => 'kimoto');
my $person_ref = \%person;

参照というのは、実際は、アドレス値のことで、単なる数値として保持していますから、数値を保存するのと同じように、変数は「$」で始まります。

数値や文字列$num, $name数値や文字列の参照$num_ref, $name_ref
配列@nums配列の参照$nums_ref
ハッシュ%personハッシュの参照$person_ref

参照は、データのアドレスを保持していますから、参照をコピーした場合は、アドレス値がコピーされるだけで、値そのものはコピーされません。

# 配列の参照
my @nums1 = (1, 2, 3);
my $nums_ref1 = \@nums;

my $nums_ref2 = $nums_ref1;

@nums1の要素を変更した場合は、$nums_ref2が指し示す配列は、同じ配列なので、変更されたように見えます。

配列の参照とハッシュの参照を直接作るためのシンタックシュガー

Perlのソースコードを読むためには、配列の参照とハッシュの参照を直接作るためのシンタックシュガーが存在するということを、覚えておきましょう。


# 配列の参照
my @nums = (1, 2, 3);
my $nums_ref = \@nums;

# 上記は以下のように書ける
my $nums_ref = [1, 2, 3];

# ハッシュの参照
my %person = (age => 1, name => 'kimoto');
my $person_ref = \%person;

# 上記は以下のように書ける
my $perlson_ref = {age => 1, name => 'kimoto'};

値と参照を区別できることは言語のメリット

Perlが誤解されているのは、Perlが値と参照を明確に区別するということが、単にわかりにくさとして、批判されてきたからです。

Perlの悪いところを過大に見せるということが、行われてきましたが、値と参照を区別していることには、明確なメリットがあります。

文字列は、デフォルトでコピーされるので安全

文字列が、デフォルトの動作でコピーされるということは、関数の渡した先で、書き換えられることはないということです。

文字列は、コピーされるので、関数の深い先で、文字列が書き換えられて、意図しない動作を起こすということが、起こらないのです。

プロジェクトが大きくなってきたときに、このありがたみを、実感できることでしょう。

Perlの文字列は、書き換えが可能

Perlの文字列は、デフォルトで書き換えが可能です。

正規表現などで、置換を行った場合に、新しい文字列が、作られるのではなく、容量が十分に確保されている場合は、その文字列を利用できます。

これは、文字列処理のパフォーマンスにとって、非常にメリットです。Perlは、文字列処理のパフォーマンスが最適化できるように、言語自体も設計されています。

コピー関数を書く必要がない

文字列のコピーは、非常によく使う機能ですが、strcopyのようなコピー関数を、プログラムの中に書く必要がありません。

配列のコピーも時々必要になりますが、関数を書かなくても、言語仕様の機能で、コピーができます。

これは、Perlプログラムが、非常に短く、スマートに書けることを意味しています。

ソフトウェアの基礎を理解できる

C言語より下の世界、たとえば、アセンブラ、機械語の世界では、メモリ上のデータは、1次元で構成されています。

これを、アドレス参照という概念を使って、まるで、多次元に見せるということが行われています。

ソフトウェアの低レベルを理解するためには、参照の概念を理解することが不可欠です。

Perlは、参照だけを持つ言語ではなく、値と参照を区別するプログラミング言語です。

簡単に記述できるPerlから初めて、参照というソフトウェアの基礎的な概念を学ぶことができます。