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から初めて、参照というソフトウェアの基礎的な概念を学ぶことができます。