2006 年 4 月 10 日 23 時 29 分

代入値の検証はどうするか


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


lvalue を使えば、プロパティ構文が使えるが、
代入はサブルーチンの中では行われない。
となると、どうやって値を検証するか。

さて substr を思い出してみよう。
substr には代入ができたはずだ。
substr も lvalue 属性がついている。
どうなっているか調べてみよう。

調べるために、注意しないといけないこともある。
lvalue サブルーチンは特別な効果を持つため、
構文上戻り値を直接代入しているように見えても
実際の、lvalue サブルーチンの挙動は異なる。

例えば、
substr($value, 1, 3) = '@@@@@';
と書いた場合は、実際は以下のように実行されている。

my $magic = substr($value, 1, 3);
$magic = '@@@@@';

つまり、substr の戻り値は一時的に変数に格納される。
そして、改めてスカラに対して代入されているのだ。

lvalue ルーチンは、最後に指定したスカラ変数を返すが、
値として返すのではなく、暗黙でリファレンスが返される。
サブルーチンの引数の @_ と同じような感じ。
見た目は値型なのだが、元の値を参照している。

なので、substr の動作を調べてみるためには、
戻り値のリファレンスを拾う必要がある。
(普通はこのような使い方はしない)

my $value = 'abcde';

my $magic_ref = \substr($value, 1, 3);
print '$value = ', $value, "\n";

$$magic_ref = '@@@@@';
print '$value = ', $value, "\n";


perl インタプリンタに直接コードを流して実行してみる。

$ perl
入力待ちになるので、上記のコードを入力。
改行などもそのまま記入できる。
最後に Ctrl+D を押して、終端の意味のコードを入力する。
Ctrl+D のあと改行すると実行される。

$value = abcde
$value = a@@@@@e


どうだろうか。substr の外で代入を行っているが、
ちゃんと後から部分置換が行われていることが分かる。
これは、マジカルスカラの効果だと解説したが、
実は、このような動作を実装することもできるのである。

以前、「Perl 5.6 で 擬似 IO レイヤ」で
ファイルハンドルへの細工を解説した。

「tie の実験」
http://mixi.jp/view_diary.pl?id=101382014&owner_id=2300658

tie は、ファイルハンドルだけでなく、
配列や連想配列、そしてスカラにも使うことができる。
上の substr の例において代入が実際に実行されるのは、
substr の返した(特別な)スカラへの代入の時だ。

つまり、tie を使ってスカラの裏側にオブジェクトを隠蔽し、
そのスカラを lvalue ルーチンによって返却すれば、
自作の lvalue 関数でも、スカラへの代入時に
コードを実行することができるはずだ。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.