Perlの謎(番外編3):『コンスタントと変換演算子のoverload』とは

Perl初心者のためのPerlノートです!

HTML/ CSS/ CGI-Perl/ JavaScript/ JavaApplet/ AccessUp/ Internet/ EnglishLearn/ ちゃいちゃん天使/ 天使メッセージ/ 飯田ワールド/ 結城ワールド/ プロフィール/ WEB相談室/ WEBアンテナ/ WEBリーダー/ 燈明日記/ yahoo

◆ はじめに

本ページは、私がPerlを習得した時(いや習得中)のノートです。

ごく普通の言語(COBOL,C,Java,VB等)を知っている人が、Perlをやり始めるといろいろと悩むことがあります。

それは、

です。

本ページは、そのようなハードルを一つ一つクリアにしていけたらと思います。

そして、本ページが何かのお役に立てれば幸いです。では、ごゆっくりご覧ください。

尚、ご感想、ご意見、誤字、脱字、間違い等がありましたら遠慮なくPerlノート掲示板へご指摘ください。

◆ サイト最新情報

◆ コンテンツ

2009-06-23 Perlの謎(番外編3):『コンスタントと変換演算子のoverload』とは

先日紹介した、結城先生のPerlクイズの以下の回答が、さっぱり分からなかったので調べてみました。

use overload '""' => sub{${+shift}*$_*2}, '0+'=>sub{${+shift}};
BEGIN {
    overload::constant (integer => sub{my $a=shift; bless \$a, 'main'})
}
http://archive.mag2.com/0000015670/20030208004000000.html

そもそも、クイズの問題は、以下の通りです。

puzzle.plという1つのスクリプトの最後の部分を示します。

このスクリプトの(省略)と書かれている部分を補って、

Figに示す実行結果とぴったり同じになるようにしてください。

◆List:前の部分が省略されたスクリプトpuzzle.pl

(省略)

$puzzle = 0;
print "$puzzle, " for (1..10);
print "\n";
$puzzle = 1;
print "$puzzle, " for (1..10);
print "\n";
$puzzle = 2;
print "$puzzle, " for (1..10);
print "\n";
$puzzle = 3;
print "$puzzle, " for (1..10);
print "\n";

◆Fig:実行結果

0, 0, 0, 0, 0, 0, 0, 0, 0, 0,

2, 4, 6, 8, 10, 12, 14, 16, 18, 20,

4, 8, 12, 16, 20, 24, 28, 32, 36, 40,

6, 12, 18, 24, 30, 36, 42, 48, 54, 60,

http://archive.mag2.com/0000015670/20030208004000000.html

では、ネットやラクダ本で私が調べたことを書きますね。

(あまり理解できていないので間違っている可能性大です)


◆コンスタントのoverload
BEGIN {
    overload::constant (integer => sub{my $a=shift; bless \$a, 'main'})
}

これは、BEGINブロックなのでコンパイル時に実行されます。

まず、コンスタント(今回は整数値)のオーバーロードをしています。

ロジックで使用している整数値すべてをオブジェクトに変換しています。

つまり、ロジック上の整数値が見つかる毎にsubが起動され、整数値は第1引数に設定されるので、それをshiftで取得し、blessしてオブジェクトに変換しています。

なぜ、オブジェクトに変換しているかと言うと、オーバーロードは、オブジェクトに対して行われるからです。

つまり、$puzzleへ代入する整数値やforの範囲演算子の1や10をオブジェクトにしてオーバーロードを可能にしています。


◆『0+』変換演算子のoverload
use overload '""' => sub{${+shift}*$_*2}, '0+'=>sub{${+shift}};

『'0+'=>sub{${+shift}}』は、オブジェクトを数値コンテキストで評価した場合にsubが起動されます。

今回の場合は、forの範囲演算子の1と10の場合です。

『${+shift}』は、起動されたsubの第1引数に数値が渡され、それをshiftで取得し、デリファレンスし、数値としてリターン値にしています。尚、数値は範囲演算子の1と10です。

尚、単項演算子の『+』は、shiftを関数として認識させるためです。『+』がないとスカラー変数 $shift になってしまう。

つまり、今回は、オブジェクトの1と10を数値の1と10へ変換しています(BEGINブロック処理の逆)。


◆『""』変換演算子のoverload

『'""' => sub{${+shift}*$_*2}』は、"$puzzle, "のようにオブジェクトが格納されている$puzzleを文字列中で評価した場合にsubが起動されます。

『'0+'=>sub{${+shift}}』で、forの範囲演算子の1と10がオブジェクトから整数値になっているので、for文が実行されて、$_には、1から10が順次格納されます。


『${+shift}*$_*2』のshiftには、$puzzleの格納オブジェクトに対応した数値が返り、数値に対応したリファレンスをデリファレンスしてから、$_と2をかけてます。

つまり、$puzzle=0の時は0で、$puzzle=1の時は1が、『${+shift}』の返り値になります。


ということで、sub{${+shift}*$_*2}は、$puzzle=1の場合、以下のようになるわけです。


1*1*2 = 2

1*2*2 = 4

:

1*9*2 = 18

1*10*2 = 20


以上です。


◆オーバーロード(overload)とは

ちなみに、オーバーロードとは、OOP用語では「多重定義」のことで、普通、関数やメソッドを多重定義しますが、もともとOOPでないPerlでは、演算子のオーバーロードしかできません。


また、演算子のオーバーロードは、オーバーライドではないので唯一でなく、見た目は同じ演算子でも、オペランドのオブジェクトで演算子が定義された場合によって複数の意味を持ちます(多態性:ポリモルフィズム)。


尚、上記今回のオーバーロードは、演算子といっても特殊な変換演算子("", 0+)とコンスタントのオーバーロードでした。


たぶん、今の実力では、おかしなことを書いている可能性が大です。

将来的には、気が付き次第、修正変更してきますね!

◆ おすすめ Perl本

■ 続・初めてのPerl 改訂版

『初めてのPerl』の次ぎに読むと吉です。

結構いいですが・・・、初心者にはちょっと難しいかもです。

■ 結城浩のPerlクイズ

この本には、ちゃいちゃんパパの小話しが載っています(謎)。

ある程度、Perlを理解している人には、たまらない内容になっています。さすが結城先生だな!

結城浩のPerlクイズ

■ 新版Perl言語プログラミングレッスン入門編

実は、私はまだ読んでいませんが、結城先生の本なので良くないはずがありません。

新版Perl言語プログラミングレッスン入門編

■ CGI&Perlポケットリファレンス (Pocket reference)

この本は、非常に役に立ちます。ちょっと調べるのに最適です。サンプルも説明も的を射ています。

CGI&Perlポケットリファレンス (Pocket reference)

■ Perlベストプラクティス

一読の価値有りだと思います。

Perlベストプラクティス

■ プログラミングPerl〈VOLUME1〉

ご存知、Perl本の聖書、ラクダ本(上)です。

■ プログラミングPerl〈VOLUME2〉

ご存知、Perl本の聖書、ラクダ本(下)です。

◆ おわりに

最後に、本ページが、何かのお役に立てれば幸いです。

尚、ご感想、ご意見、誤字、脱字、間違い等がありましたら遠慮なくPerlノート掲示板へご指摘ください。

HTML/ CSS/ CGI-Perl/ JavaScript/ JavaApplet/ AccessUp/ Internet/ EnglishLearn/ ちゃいちゃん天使/ 天使メッセージ/ 飯田ワールド/ 結城ワールド/ プロフィール/ WEB相談室/ WEBアンテナ/ WEBリーダー/ 燈明日記/ yahoo

人のよいところをどんどん見つけよう