Perlのエラーメッセージのコーナー。
Perlのエラーメッセージが表示される最小のプログラムを書いて、どういうときにどう怒られるかを研究する。
家庭の事情が終息するまで、困ったときのエラーメッセージ頼みで進行します。

今回のお題は
Ambigous use of %s1 resolved as %s2
である。
ちなみにラクダ本の原著では「Ambigous use of %s resolved as %s」であったが%s1、%s2のように区別した。
いずれにも何らかの文字列が入る。
%sというのはprintfのテンプレートなので、本来%s1などと書くべきではないが、大目に見てください。

Emblem Perl
これはSVの第1文型の英文で、受動態のbe動詞が略されている。
 S(主語)Ambigous use of %s1
 V(動詞)(is) resolved
 M(修飾語)as %s
訳すと「%s1を曖昧に使っているが、これは %2のように解釈した」ということである。

あいまいなプログラムなんか書くのは結構たいへんである。
プログラミング言語は、常に人間の言うことを1つの意味で解釈する。
Perlなど、コンテキストがあるから適当に解釈してくれているんだろうと過大評価(あるいは過小評価)されているが、実際にはコンテキストの適用にも規則があって、それに従っているに過ぎない。
他にも、人間の書いたプログラムで曖昧な点があれば、Perlは「一応こう解釈してみました」と報告してくれる、というのがこのメッセージの趣旨だ。
いろいろなケースでこのメッセージが出るだろうが、ここではネットをサーチして分かった1件だけ述べる。
#! /usr/bin/perl
#
# weightControl.pl

use 5.10.0;
use warnings;

$x = 82;
say "Hello, I'm Perl! The number is $xkg";
上のプログラムは、$xというスカラーにぼくの体重82キロを書いて、最後にkgという単位を付けて表示している。
見るからにダメそうだが、ダメなりに実行していいですか。
$ weightControl.pl
Name "main::x" used only once: possible typo at ./weightControl.pl line 8.
Name "main::xkg" used only once: possible typo at ./weightControl.pl line 9.
Use of uninitialized value $xkg in concatenation (.) or string at ./weightControl.pl line 9.
Hello, I'm Perl! The number is
[perl]$
要するに$xというスカラーと$xkgというスカラーが現れてしまっている。
二重引用符の中で$xというスカラーとkgという単位のつもりの文字列が融合してしまったのである。
解決法にはいくつかあるが、${x}と名前をブレース囲みにするのがその1つだ。
#! /usr/bin/perl
#
# weightControl.pl

use 5.10.0;
use warnings;

$x = 82;
say "Hello, I'm Perl! The number is ${x}kg";
実行してみる。
$ weightControl.pl
Hello, I'm Perl! The number is 82kg
OKだ。
ところで、この$xのことを${x}と書く記法を、最初の代入文にも適用してみる。
#! /usr/bin/perl
#
# weightControl.pl

use 5.10.0;
use warnings;

${x} = 82;
say "Hello, I'm Perl! The number is ${x}kg";
実行してみる。
$ weightControl.pl
Ambiguous use of ${x} resolved to $x at ./weightControl.pl line 8.
Hello, I'm Perl! The number is 82kg
確かに警告が出た。
これは、${x}という式には複数の解釈が成り立つが、一応$xとして解釈しておきましたよと告げてくれている。
use warningsプラグマを使わないと表示されない。

これは、xという演算子があることが原因である。
xというのは文字列を繰り返す演算子で、たとえば $foo = 'bar' x 3 と書くと $foo には「barbarbar」が入る。
この演算子が、引数なしに現れたのかもしれないけど、そんなのありえそうにはないから、その解釈は取らなかった、ということだ。
警告さえ無視すれば動くところではあるけど、警告は警告で気持ち悪いから、では直してみよう。
カンタンなのはxではなくもっと意味のあるワードにすることだ。
#! /usr/bin/perl
#
# weightControl.pl

use 5.10.0;
use warnings;

${weight} = 82;
say "Hello, I'm Perl! The number is ${weight}kg";
実行してみる。
$ weightControl.pl
Hello, I'm Perl! The number is 82kg
OKだった。
でも、よく考えたら、${weight}という記法は二重引用符の外でわざわざ使うことはない。
プログラムとしての完成版は
#! /usr/bin/perl
#
# weightControl.pl

use 5.10.0;
use warnings;

$weight = 82;
say "Hello, I'm Perl! The number is ${weight}kg";
であろう。
ともかく、xという文字1字だと、Perlは文字列反復演算子と紛れてまぎらわしいことが分かった。

この警告は珍しく、もっと他のパターンもあるだろうが把握していない。
また他で遭遇したらここで紹介する。

エラーメッセージが出たら、そのエラーメッセージが出る最小のコードと共に、自分のエラーメッセージコレクションとして取っておくことが大事だと思う。
関数や演算子や正規表現のサンプルコード(成功例)を取っておくことはよくやるが、失敗例も取っておくといいと思う。
ただ発表しないとリキが出ないのでその場合はこういうブログが有効だろう。