さて今日はエラー メッセージをあえて出すコーナー、今日のお題は「"our" variable is redeclared」です。「our変数が再定義された(のはおかしい)」という意味です。
エラー メッセージをABC順に制覇しているのですが、今日も『かんたんPerl』レベルでは出なくて、『すぐわかるオブジェクト指向Perl』レベルの警告です。
(まあ、警告なんか出さないに越したことはないんですが…)

エラー メッセージをABC順に制覇しているのですが、今日も『かんたんPerl』レベルでは出なくて、『すぐわかるオブジェクト指向Perl』レベルの警告です。
(まあ、警告なんか出さないに越したことはないんですが…)

use strict宣言をすると、use strict "refs"(シンボリック リンクの禁止)、use strict "subs"(裸のワードの禁止)、use strict "vars"(無修飾の変数の禁止"という3つの禁止が同時に行われています。
use strict "vars"で禁止されるのは、以下のようなプログラムです。
実行します。
今はuse strictではないので怒られません。
怒られてみます。
どうでしょう。
ちゃんと怒られました。
$iはパッケージ修飾されていない、ということですね。
どうすれば直るでしょう。
そう、myですね。
どうだ。
さて、プログラムはデフォルトでmainというパッケージに入っているので、こうしても動いたんです。
どうでしょうか。
へぇー。
ちなみに、my宣言しなくても、パッケージ修飾しなくても怒られない変数があって、それは$_、@_、@ARGV、$/、$a、$bなどのPerl組み込みの変数です。
($a、$bって何に使う変数か分かりますか?)
それ以外の名前で、mainパッケージ以外で使うにはどうすればいいでしょうか。ここでは、よくあるパターンで、ファイルが2個に分けます。
メインプログラムである
と、パッケージモジュールである
です。実行します。
解説します。
makeVar.pmでは最初にmakeVarパッケージを宣言しています。
この中でour宣言をすると、そのパッケージに属する変数を定義できます。
そのパッケージの中では、修飾無しでそれを使えます。
ourVar.pmでは、makeVar.pmをuseし、その中のパッケージ変数$iを参照しています。
その場合は、$makeVar::iと、パッケージ修飾しなければ使えません。
パッケージ修飾を忘れて怒られてみてもいいですか。
どうですか。
そのエラーさっきも見たわ!
予定の行動ですね。
さて、今日のお題のエラーは、our宣言がダブったというやつです。
さっきうまくいったプログラムから、このpmを呼び出して実行してみます。
どうですか。
わーいちゃんと怒られましたね。(マゾ…)
怒られながらもちゃんと実行はされていて、2回めのour宣言とともに代入した値が入っています。
use strict "vars"で禁止されるのは、以下のようなプログラムです。
#! /usr/local/bin/perl
# lonelyVar.pl -- 修飾のない変数
#use strict; # あえて無効化
use warnings;
use 5.010;
$i = 3;
say "\$iは$iです!";
# lonelyVar.pl -- 修飾のない変数
#use strict; # あえて無効化
use warnings;
use 5.010;
$i = 3;
say "\$iは$iです!";
実行します。
[sample]$ ./lonelyVar.pl
$iは3です!
$iは3です!
今はuse strictではないので怒られません。
怒られてみます。
#! /usr/local/bin/perl
# lonelyVar2.pl -- 修飾のない変数(エラーになります)
use strict; # 有効化
use warnings;
use 5.010;
$i = 3;
say "\$iは$iです!";
# lonelyVar2.pl -- 修飾のない変数(エラーになります)
use strict; # 有効化
use warnings;
use 5.010;
$i = 3;
say "\$iは$iです!";
どうでしょう。
[sample]$ ./lonelyVar2.pl
Global symbol "$i" requires explicit package name at ./lonelyVar2.pl line 8.
Global symbol "$i" requires explicit package name at ./lonelyVar2.pl line 9.
Execution of ./lonelyVar2.pl aborted due to compilation errors.
Global symbol "$i" requires explicit package name at ./lonelyVar2.pl line 8.
Global symbol "$i" requires explicit package name at ./lonelyVar2.pl line 9.
Execution of ./lonelyVar2.pl aborted due to compilation errors.
ちゃんと怒られました。
$iはパッケージ修飾されていない、ということですね。
どうすれば直るでしょう。
そう、myですね。
#! /usr/local/bin/perl
# lonelyVar3.pl -- 修飾のない変数(OK)
use strict; # 有効化
use warnings;
use 5.010;
my $i = 3;
say "\$iは$iです!";
# lonelyVar3.pl -- 修飾のない変数(OK)
use strict; # 有効化
use warnings;
use 5.010;
my $i = 3;
say "\$iは$iです!";
どうだ。
[sample]$ ./lonelyVar3.pl
$iは3です!
$iは3です!
さて、プログラムはデフォルトでmainというパッケージに入っているので、こうしても動いたんです。
#! /usr/local/bin/perl
# lonelyVar4.pl -- 修飾のない変数(FQN)
use strict; # 有効化
use warnings;
use 5.010;
$main::i = 3;
say "\$iは$main::iです!";
# lonelyVar4.pl -- 修飾のない変数(FQN)
use strict; # 有効化
use warnings;
use 5.010;
$main::i = 3;
say "\$iは$main::iです!";
どうでしょうか。
[sample]$ ./lonelyVar4.pl
$iは3です!
[sample]$
$iは3です!
[sample]$
へぇー。
ちなみに、my宣言しなくても、パッケージ修飾しなくても怒られない変数があって、それは$_、@_、@ARGV、$/、$a、$bなどのPerl組み込みの変数です。
($a、$bって何に使う変数か分かりますか?)
それ以外の名前で、mainパッケージ以外で使うにはどうすればいいでしょうか。ここでは、よくあるパターンで、ファイルが2個に分けます。
メインプログラムである
#! /usr/local/bin/perl
# ourVar.pl -- パッケージ変数を使う
use strict; # 有効化
use warnings;
use 5.010;
use makeVar;
say "\$makeVar::iは$makeVar::iです!";
# ourVar.pl -- パッケージ変数を使う
use strict; # 有効化
use warnings;
use 5.010;
use makeVar;
say "\$makeVar::iは$makeVar::iです!";
と、パッケージモジュールである
#! /usr/local/bin/perl
# makeVar.pm -- パッケージ変数を作る
use strict;
use warnings;
use 5.010;
package makeVar;
our $i = 3;
say "パッケージ", __PACKAGE__, "において\$iを宣言しました。値は$iです";
# makeVar.pm -- パッケージ変数を作る
use strict;
use warnings;
use 5.010;
package makeVar;
our $i = 3;
say "パッケージ", __PACKAGE__, "において\$iを宣言しました。値は$iです";
です。実行します。
[sample]$ ./ourVar.pl
パッケージmakeVarにおいて$iを宣言しました。値は3です
$makeVar::iは3です!
パッケージmakeVarにおいて$iを宣言しました。値は3です
$makeVar::iは3です!
解説します。
makeVar.pmでは最初にmakeVarパッケージを宣言しています。
この中でour宣言をすると、そのパッケージに属する変数を定義できます。
そのパッケージの中では、修飾無しでそれを使えます。
ourVar.pmでは、makeVar.pmをuseし、その中のパッケージ変数$iを参照しています。
その場合は、$makeVar::iと、パッケージ修飾しなければ使えません。
パッケージ修飾を忘れて怒られてみてもいいですか。
#! /usr/local/bin/perl
# ourVar2.pl -- パッケージ変数を無修飾で使う(とエラー)
use strict; # 有効化
use warnings;
use 5.010;
use makeVar;
say "\$iは$iです!";
# ourVar2.pl -- パッケージ変数を無修飾で使う(とエラー)
use strict; # 有効化
use warnings;
use 5.010;
use makeVar;
say "\$iは$iです!";
どうですか。
[sample]$ ./ourVar2.pl
パッケージmakeVarにおいて$iを宣言しました。値は3です
Global symbol "$i" requires explicit package name at ./ourVar2.pl line 10.
Execution of ./ourVar2.pl aborted due to compilation errors.
パッケージmakeVarにおいて$iを宣言しました。値は3です
Global symbol "$i" requires explicit package name at ./ourVar2.pl line 10.
Execution of ./ourVar2.pl aborted due to compilation errors.
そのエラーさっきも見たわ!
予定の行動ですね。
さて、今日のお題のエラーは、our宣言がダブったというやつです。
#! /usr/local/bin/perl
# makeVar2.pm -- パッケージ変数を作る(エラー
use strict;
use warnings;
use 5.010;
package makeVar2;
our $i = 3;
our $i = "ROBOT"; # ここが怒られる!
say "パッケージ", __PACKAGE__, "において\$iを宣言しました。値は$iです";
# makeVar2.pm -- パッケージ変数を作る(エラー
use strict;
use warnings;
use 5.010;
package makeVar2;
our $i = 3;
our $i = "ROBOT"; # ここが怒られる!
say "パッケージ", __PACKAGE__, "において\$iを宣言しました。値は$iです";
さっきうまくいったプログラムから、このpmを呼び出して実行してみます。
#! /usr/local/bin/perl
# ourVar3.pl -- パッケージ変数を使う
use strict; # 有効化
use warnings;
use 5.010;
use makeVar2; # ourを2回やってるやつ
say "\$makeVar2::iは$makeVar2::iです!";
# ourVar3.pl -- パッケージ変数を使う
use strict; # 有効化
use warnings;
use 5.010;
use makeVar2; # ourを2回やってるやつ
say "\$makeVar2::iは$makeVar2::iです!";
どうですか。
[sample]$ ./ourVar3.pl
"our" variable $i redeclared at makeVar2.pm line 11.
パッケージmakeVar2において$iを宣言しました。値はROBOTです
$makeVar2::iはROBOTです!
"our" variable $i redeclared at makeVar2.pm line 11.
パッケージmakeVar2において$iを宣言しました。値はROBOTです
$makeVar2::iはROBOTです!
わーいちゃんと怒られましたね。(マゾ…)
怒られながらもちゃんと実行はされていて、2回めのour宣言とともに代入した値が入っています。