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

Perlのエラーメッセージが表示される最小のプログラムを書いて、どういうときにどう怒られるかを研究する。
今回のお題は
Argment "%s" isn't numericである。
これはSVCの第2文型の否定形だ。
S(主語)Argment "%s"
V(動詞)isn't
C(保護)numeric
訳すと「引数%sは数値ではない(本来数値であるべきだった)」ということである。
足し算とかであろうか。
まずエラーの出ないパターンをやってみる。
実行する。
ここで、$weightについうっかり"two"という文字列を加算してしまったとする。
「引数"two"は数字ではない」というお題のメッセージのあとに「weightControl.plの9行目の加算(+)演算子において」というメッセージが表示されている。
親切だ。
なお、このメッセージは警告であって、その後82を表示する。
これ、"two"という文字列を足し算に使ってるけどおかしくないですか?
といいながら、ゼロを足しているのだ。
"2kg"という文字列を足し算大丈夫ですか?
といいながら、「2」を足している。
「two」という文字列は数値コンテキストで無理やり解釈するとゼロになる。
「2kg」という文字列は数値コンテキストで無理やり解釈すると2になる。
ちなみに「2kg200g」も2になる。
へぇー。
でもこんなの覚えたってしょうがない。
「文字列を数値として使うとどうなるか」覚えて、プログラムで使っても可読性が下がるだけである。
やめてください。
ちなみに、BASICやJavaScriptなどの言語では、+演算子が数値の加算の他に文字列の連結を兼ねている場合が多いが、Perlでは文字列の連結にはドット演算子(.)が使われる。
Larry Wallによると「数値の加算は可換(前後の引数の交換が同値)だが、文字列の連結はそうではないので、同じ演算子になるのはおかしい」ということである。
さて、2は数値で"two"は文字列であるが、引用符で囲んだ"2"は文字列であろうか数値であろうか。
これを数値コンテキスト(contextは文脈のこと)と言う。
逆に、+演算子ではなく.演算子を使うと文字列として解釈される。
これを文字列コンテキストという。
"82"に"2"を連結しているのである。
さて、引用符なしの2をドット演算子に渡したらどうなるだろうか。
つまり、数字リテラルをドット演算子に渡しても、特に怒られず、平然と文字列として結合する。
ということで
・2という数値を+演算子に渡すと2を加算する(当たり前)
・"two"という文字列を+演算子に渡すと、警告してゼロを加算する
・"2kg"という文字列を+演算子に渡すと、警告して2を加算する
・"2"という文字列を+演算子に渡すと、数字コンテキストで解釈して2を加算する
・"2"という文字列を.演算子に渡すと、文字列コンテキストで解釈して"2"を連結する
・2という数値を.演算子に渡すと、文字列コンテキストで解釈して"2"を連結する
2という数値を文字列として扱っても"2"という文字列であろうと解釈するのは自然だから、いちいち警告せずに"2"を連結する。
"2kg"という文字列を数値として扱うというのはどうするかわからないから、警告を出して2を加算する。
ということで、非対称性がある。
S(主語)Argment "%s"
V(動詞)isn't
C(保護)numeric
訳すと「引数%sは数値ではない(本来数値であるべきだった)」ということである。
足し算とかであろうか。
まずエラーの出ないパターンをやってみる。
#! /usr/bin/perl上のプログラムは、$xというスカラーにぼくの体重82キロを書いて、さらに2を足して表示している。
#
# weightControl.pl
use 5.10.0;
use warnings;
$weight = 82;
$weight = $weight + 2;
say "Hello, I'm Perl! The number is ${weight}kg";
実行する。
$ weightControl.pl無事84kgになった。
Hello, I'm Perl! The number is 84kg
$
ここで、$weightについうっかり"two"という文字列を加算してしまったとする。
#! /usr/bin/perl実行してみる。
#
# weightControl.pl
use 5.10.0;
use warnings;
$weight = 82;
$weight = $weight + "two";
say "Hello, I'm Perl! The number is ${weight}kg";
$ weightControl.pl出たね。
Argument "two" isn't numeric in addition (+) at ./weightControl.pl line 9.
Hello, I'm Perl! The number is 82kg
「引数"two"は数字ではない」というお題のメッセージのあとに「weightControl.plの9行目の加算(+)演算子において」というメッセージが表示されている。
親切だ。
なお、このメッセージは警告であって、その後82を表示する。
これ、"two"という文字列を足し算に使ってるけどおかしくないですか?
といいながら、ゼロを足しているのだ。
#! /usr/bin/perlだと
#
# weightControl.pl
use 5.10.0;
use warnings;
$weight = 82;
$weight = $weight + "2kg";
say "Hello, I'm Perl! The number is ${weight}kg";
$ weightControl.plとなる。
Argument "2kg" isn't numeric in addition (+) at ./weightControl.pl line 9.
Hello, I'm Perl! The number is 84kg
"2kg"という文字列を足し算大丈夫ですか?
といいながら、「2」を足している。
「two」という文字列は数値コンテキストで無理やり解釈するとゼロになる。
「2kg」という文字列は数値コンテキストで無理やり解釈すると2になる。
ちなみに「2kg200g」も2になる。
へぇー。
でもこんなの覚えたってしょうがない。
「文字列を数値として使うとどうなるか」覚えて、プログラムで使っても可読性が下がるだけである。
やめてください。
ちなみに、BASICやJavaScriptなどの言語では、+演算子が数値の加算の他に文字列の連結を兼ねている場合が多いが、Perlでは文字列の連結にはドット演算子(.)が使われる。
Larry Wallによると「数値の加算は可換(前後の引数の交換が同値)だが、文字列の連結はそうではないので、同じ演算子になるのはおかしい」ということである。
さて、2は数値で"two"は文字列であるが、引用符で囲んだ"2"は文字列であろうか数値であろうか。
#! /usr/bin/perlで実行してみると、何の問題もなく2が加算される。
#
# weightControl.pl
use 5.10.0;
use warnings;
$weight = 82;
$weight = $weight + "2";
say "Hello, I'm Perl! The number is ${weight}kg";
$ weightControl.plPerlのデータは融通が効き、数値が要求される局面に文字列を渡しても、その文字列が数値として解釈できれば適宜数値として解釈する。
Hello, I'm Perl! The number is 84kg
$
これを数値コンテキスト(contextは文脈のこと)と言う。
逆に、+演算子ではなく.演算子を使うと文字列として解釈される。
これを文字列コンテキストという。
#! /usr/bin/perl実行するとこうなる。
#
# weightControl.pl
use 5.10.0;
use warnings;
$weight = 82;
$weight = $weight . "2";
say "Hello, I'm Perl! The number is ${weight}kg";
$ weightControl.pl八百二十二キロはやばい。
Hello, I'm Perl! The number is 822kg
$
"82"に"2"を連結しているのである。
さて、引用符なしの2をドット演算子に渡したらどうなるだろうか。
#! /usr/bin/perl実行。
#
# weightControl.pl
use 5.10.0;
use warnings;
$weight = 82;
$weight = $weight . 2;
say "Hello, I'm Perl! The number is ${weight}kg";
$ weightControl.pl
Hello, I'm Perl! The number is 822kg
$
つまり、数字リテラルをドット演算子に渡しても、特に怒られず、平然と文字列として結合する。
ということで
・2という数値を+演算子に渡すと2を加算する(当たり前)
・"two"という文字列を+演算子に渡すと、警告してゼロを加算する
・"2kg"という文字列を+演算子に渡すと、警告して2を加算する
・"2"という文字列を+演算子に渡すと、数字コンテキストで解釈して2を加算する
・"2"という文字列を.演算子に渡すと、文字列コンテキストで解釈して"2"を連結する
・2という数値を.演算子に渡すと、文字列コンテキストで解釈して"2"を連結する
2という数値を文字列として扱っても"2"という文字列であろうと解釈するのは自然だから、いちいち警告せずに"2"を連結する。
"2kg"という文字列を数値として扱うというのはどうするかわからないから、警告を出して2を加算する。
ということで、非対称性がある。