Perlのエラーメッセージのコーナー。
Perlのエラーメッセージが表示される最小のプログラムを書いて、どういうときにどう怒られるかを研究する。

今回は
Can't modify non-lvalue subroutine call
を研究する。

Aerosol.png

(実際には、ABC順にやっていて「%s package attribute may clash with future reserved word: %s」というのを研究する番だったのだが、これに出てくるattributeというものを研究していたら十分長くなったので、その研究の過程で出てくる上のメッセージを研究することになった。)

これは、

(主語S):(You、Perl)(省略)
(動詞V):Can't modify
(目的語O):non-lvalue subroutine call

という第3文型の文で、

(主語S):(あなたは、Perlは)(省略)
(動詞V):変更がすることが出来ない
(補語C):左辺値でないサブルーチン呼び出しを

だから
左辺値ではないサブルーチン呼び出しを変更することはできない
という訳になる。
このように英語でも先頭の主語を省略することがある。

lvalueがleft valueの略で「左辺値」と訳すところがミソ。

Perlの関数は、代入文の左辺になれるものがある。
たとえばsubstrがそうだ。
#! /usr/local/bin/perl
#
# substr_test.pl -- substr関数で遊ぼう

use 5.010;
use strict;
use warnings;

my $date = "20141123";

say "\$date:", $date;
say "今年は何年:", substr($date, 0, 4);
say "年を8888にする:", substr($date, 0, 4) = "8888"; # ここが左辺値!
say "現在の\$dateは:", $date;
実行する。
$ substr_test.pl
$date:20141123
今年は何年:2014
年を8888にする:8888
現在の$dateは:88881123
1個目のsubstrは$dateという変数の先頭から4文字を取り出してその値を返す。
問題は2個目で、代入文の左側に来ているので$dateの先頭4文字が8888に置き換わっている。
不思議ふしぎ。

このような、左辺にくるサブルーチンを自作することもできる。
この場合lvalue属性というのを使う。

次のプログラムでは、1を加算するサブルーチンincを書いてみた。
#! /usr/local/bin/perl
#
# subrtn_test.pl -- サブルーチンで遊ぼう

use 5.010;
use strict;
use warnings;

my $num = 9;

say "\$num:", $num;
say "inc:", &inc($num);
say "\$num:", $num;

&inc($num) = 99999999; #左辺値で使う

say "\$num:", $num;

sub inc : lvalue {
$num++;
$num; # 左辺値として扱われた時代入する変数を返す
}
実行してみた。
$ subrtn_test.pl
$num:9
inc:10
$num:10
$num:99999999
このように、左辺値で使うサブルーチンは、右辺で使う場合は(値を返すときは)戻り値になり、左辺で使うときは(代入するときは)代入対象になる変数を返す。

それだけではダメで、サブルーチンの右に、コロン(:)で挟んでlvalueというキーワードを書く。
これをlvalue属性という。

試みに、上のプログラムをいじってlvalueを取ってみる。
#! /usr/local/bin/perl
#
# subrtn_test.pl -- サブルーチンで遊ぼう(間違ったプログラム)

use 5.010;
use strict;
use warnings;

my $num = 9;

say "\$num:", $num;
say "inc:", &inc($num);
say "\$num:", $num;

&inc($num) = 99999999; #左辺値で使う

say "\$num:", $num;

sub inc { # lvalueを取る
 $num++;
 $num; # 左辺値として扱われた時代入する変数を返す
}
実行してみる。
$ subrtn_test.pl
$num:9
inc:10
$num:10
Can't modify non-lvalue subroutine call at /Users/query1000/perl/subrtn_test.pl line 15.
ちゃんと怒られる。
「ちゃんと怒られる」って言い方も変だけどね。