このアーカイブは同期化されません。 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 関数でも、スカラへの代入時に
コードを実行することができるはずだ。