Perlのエラーメッセージのコーナー。
Perlのエラーメッセージが表示される最小のプログラムを書いて、どういうときにどう怒られるかを研究する。
今回は
を研究する。
(※今日の記事はスッキリ終わりません!)
Perlのエラーメッセージが表示される最小のプログラムを書いて、どういうときにどう怒られるかを研究する。
今回は
%s did not return a true value
を研究する。
(※今日の記事はスッキリ終わりません!)
これは、
(主語S):%s
(動詞V):did not return
(目的語O): a true value
という第2文型の文で、
(主語S):%s
(動詞V):は返さなかった
(補語C):真値を
という意味になる。
これは、useで取り込むモジュール ファイルが真の値を返さなかった時に発生する。
以下は、昨年6月に寄稿したSoftware Design誌の原稿「Perlによるオブジェクト指向入門」の例題プログラムで解説する。
以下は、誌面に載った(エラーにならない)プログラムである。
まずmyDate.pmというモジュールを作成する。
このモジュールを使うメインプログラムを書く。
では、末尾の「1;」を「0;」に変えてみる。
さて、どのようなものが真として解釈され、どのようなものが偽として解釈されるのだろうか。
こうなっている。
(偽になるもの)
・数値 0
・文字列 ""
・文字列 "0"
・空リスト
・undef
・偽を返した関数値
(真になるもの)
・ゼロ以外の数値
・空文字列、"0"以外の文字列
・中身のあるリスト
・真を返した関数値
これは「真実と偽り」とは関係がない。
上のモジュールを以下のようにしてみる。
このように、いくらでも凝った値をモジュールを締めくくる真値として使うことができるが、こんなことで個性を発揮してもしょうがないので「1;」と書いたほうが良い。
ラクダ本のuse関数の解説には「useはrequireを呼ぶ」と書かれていて、requireの解説には「初期化コードが正しく終了したことを示すためにモジュールは真を返す。ために慣例的に1;と書く」と書かれている。
なお、Perl 5.14からはパッケージをブロックにすると、package関数が真を返すために1;を書く必要がなくなるそうだ。
Perl 5.13.2 がもたらした package NAMESPACE BLOCK 構文があたえるもの - blog.64p.org
モジュールの末尾に「1;」と書きたくない人のためのパッケージブロック構文 - サンプルコードによるPerl入門 ~ Perlで楽しくプログラミングを学ぼう ~
こうなる。
「}」の前に「1;」を入れると無事に実行できる。
ううん、研究課題である。
(主語S):%s
(動詞V):did not return
(目的語O): a true value
という第2文型の文で、
(主語S):%s
(動詞V):は返さなかった
(補語C):真値を
という意味になる。
%sは真値を返さなかったという訳になる。
これは、useで取り込むモジュール ファイルが真の値を返さなかった時に発生する。
以下は、昨年6月に寄稿したSoftware Design誌の原稿「Perlによるオブジェクト指向入門」の例題プログラムで解説する。
以下は、誌面に載った(エラーにならない)プログラムである。
まずmyDate.pmというモジュールを作成する。
# myDate.pm -- 日付のモジュールこの最後の「1;」がミソで、モジュールが真の値を返すためにムリヤリ入れている。
use strict;
use warnings;
package myDate;
use overload
'""' => 'toString',
'+' => 'add',
;
sub new {
my ($class, $date) = @_;
unless (defined $date and $date =~ /(\d+)(\d\d)(\d\d)/) { # 5桁以上の数字かチェック
die "myDate: date $date should be 5 or more digits numeric!";
} else {
bless { date => $date, y => $1, m => $2, d => $3 } => $class;
}
}
sub add {
my ($self, $add) = @_;
my ($date, $y, $m, $d) = ($self->{date}, $self->{y}, $self->{m}, $self->{d});
for (1..$add) { # 加算する日付のぶんループする
if ($m == 12 and $d == 31) { # 大晦日
++$y; $m = 1; $d = 1;
} elsif ((&leap($y) and $m == 2 and $d == 29) # 月末
or ($m == 2 and $d == 28)
or (($m == 4 or $m == 6 or $m == 9 or $m == 11) and $d == 30)
or ($d == 31)) {
++$m; $d = 1;
} else { # それ以外
++$d;
}
}
$date = $y. sprintf("%02d", $m). sprintf("%02d", $d); # 1桁の場合はゼロを付加
bless { date => $date, y => $y, m => $m, d => $d } => ref $self;
}
sub toString { # 文字列スカラーに変換する
return shift->{date}; # shiftは第1引数=オブジェクトそのもの
}
sub leap { # うるう年なら真を、それ以外なら偽を返す
my $y = shift;
return 1 if $y % 400 == 0;
return 0 if $y % 100 == 0;
return 1 if $y % 4 == 0;
return 0;
}
1;
このモジュールを使うメインプログラムを書く。
#! /bin/perlでは実行してみる。
#
# myDateTest.pl -- 日付のテスト
use strict;
use warnings;
use myDate;
my $date = myDate->new(shift);
print "Date is $date\n";
$date = $date->add(10);
print "10 days after is $date\n";
print "30 days after is ", $date + 30, "\n";
$ myDateTest.pl 20140305エラーは出ていない。
Date is 20140305
10 days after is 20140315
30 days after is 20140414
$
では、末尾の「1;」を「0;」に変えてみる。
# myDate.pm -- 日付のモジュールである。
use strict;
use warnings;
package myDate;
。。中略。。
0;
$ myDateTest.pl 20140305たしかに目的のエラーメッセージが表示された。
myDate.pm did not return a true value at /Users/query1000/perl/myDateTest.pl line 7.
BEGIN failed--compilation aborted at /Users/query1000/perl/myDateTest.pl line 7.
$
さて、どのようなものが真として解釈され、どのようなものが偽として解釈されるのだろうか。
こうなっている。
(偽になるもの)
・数値 0
・文字列 ""
・文字列 "0"
・空リスト
・undef
・偽を返した関数値
(真になるもの)
・ゼロ以外の数値
・空文字列、"0"以外の文字列
・中身のあるリスト
・真を返した関数値
これは「真実と偽り」とは関係がない。
上のモジュールを以下のようにしてみる。
# myDate.pm -- 日付のモジュール実行する。
use strict;
use warnings;
package myDate;
。。中略。。
”郵便ポストは青い”;
$ myDateTest.pl 20140305明らかな嘘、いつわりでモジュールを締めくくったにも関わらず、モジュールはちゃんとuseされ、プログラムはちゃんと実行された。
Date is 20140305
10 days after is 20140315
30 days after is 20140414
$
このように、いくらでも凝った値をモジュールを締めくくる真値として使うことができるが、こんなことで個性を発揮してもしょうがないので「1;」と書いたほうが良い。
ラクダ本のuse関数の解説には「useはrequireを呼ぶ」と書かれていて、requireの解説には「初期化コードが正しく終了したことを示すためにモジュールは真を返す。ために慣例的に1;と書く」と書かれている。
なお、Perl 5.14からはパッケージをブロックにすると、package関数が真を返すために1;を書く必要がなくなるそうだ。
Perl 5.13.2 がもたらした package NAMESPACE BLOCK 構文があたえるもの - blog.64p.org
モジュールの末尾に「1;」と書きたくない人のためのパッケージブロック構文 - サンプルコードによるPerl入門 ~ Perlで楽しくプログラミングを学ぼう ~
こうなる。
# myDate.pm -- 日付のモジュールやってみた。
use strict;
use warnings;
package myDate {
。。中略。。
}
$ myDateTest.pl 20140305ダメだー。
myDate.pm did not return a true value at /Users/query1000/perl/myDateTest.pl line 7.
BEGIN failed--compilation aborted at /Users/query1000/perl/myDateTest.pl line 7.
$
「}」の前に「1;」を入れると無事に実行できる。
ううん、研究課題である。