our
前回のlocal妥協に伴い、いろいろ調べていくうちにlocalより先にourやったほうがわかりやすいんじゃないかと思ったので先にourから。
our
http://d.hatena.ne.jp/perlcodesample/20080311/1205249391
### パッケージ変数の宣言
# ・パッケージ変数の宣言は、our で行う。
# ・パッケージ変数の宣言により、
# 1. パッケージ変数が生成され、
# 2. 完全修飾名を、修飾されない変数名で参照できる。
# ( $SomePackgae::var を $var で参照できるということ。)
パッケージ変数
http://d.hatena.ne.jp/perlcodesample/20080308/1204953841
# パッケージ変数
# ・パッケージ変数とは、名前空間に属するグローバル変数である。
# ・つまり、パッケージ変数は、修飾名(パッケージ名)を持ち、
# ソースコードのどの位置からでも参照できるということです。
パッケージ
http://www.geocities.jp/ky_webid/perl5/036.html
明示的にパッケージを使わなくとも、暗黙のうちに main という名前のパッケージが使われています。通常、これを意識する必要はありませんが、明示的に書くこともできます。
mainパッケージ
http://d.hatena.ne.jp/perlcodesample/20080313/1205429891
mainパッケージ
* パッケージの宣言が行われない場合、ourで宣言されたパッケージ変数は、mainパッケージに属する。
Perlの変数の種類
* Perlには、グローバル変数は、存在せず、パッケージ変数とレキシカル変数しか存在しない。
* グローバル変数のように見えるものは、実は、mainパッケージに属している。
ourへ戻る
#!/usr/bin/perl use strict; use warnings; our $global = "abc"; print "$global\n"; # scope1 { print "in scope1 = $global\n"; } print "$main::global\n";
C:\MyWorks\Perl\our>perl our1.pl abc in scope1 = abc abc
おさらいすると
- パッケージを省略した場合はデフォルトでmainパッケージになる
- ここでの$globalはmainパッケージのグローバル変数
- パッケージの中にいるときは修飾名なしでアクセスできる
ということでいいのかな。
パッケージを指定してやってみる。
#!/usr/bin/perl use strict; use warnings; package pkg; my $pkgmy = 10; print "pkg:: $pkgmy\n"; our $pkgmy; package main; print "main->pkg:: $pkg::pkgmy\n";
Use of uninitialized value in concatenation (.) or string at our2.pl line 14. pkg:: 10 main->pkg::
初期化されてないときた。
pkg:: 10
main->pkg:: 10
というのを想定していたがならなかった。なぜか。
単純にmyとourを理解していなかった。
myはスコープ内でローカルという意味で、パッケージの下に書いたとしてもこの場合はファイルスコープのmy、つまりmainパッケージのmyということ。
で、ourはmyをパッケージ変数に変換してくれると勝手に勘違いしていた。
というわけでやり直し。
#!/usr/bin/perl use strict; use warnings; package pkg; our $pkgour = 10; print "pkg:: $pkgour\n"; package main; print "main->pkg:: $pkg::pkgour\n";
C:\MyWorks\Perl\our>perl our3.pl pkg:: 10 main->pkg:: 10
まあこんなコード書いても何が便利なのかわからないけど、おそらくクラスのプロパティとかで使うのかなあというわけで書いてみたが
package pkg; { our $pkgour 10; } print "main->pkgour:: $pkg::pkgour\n";
こんなの書いたら豪快にエラーがきた。
JavaScriptだとこれでいけるのにPerlはダメらしい。
{ package pkg; our $pkgour 10; } print "main->pkgour:: $pkg::pkgour\n";
こう書くといける。
となると疑問があって、メソッドなんか書く場合
http://d.hatena.ne.jp/perlcodesample/20080612/1213415372
- サブルーチンは、スコープの影響を受けません。
- 一見すると、fucnは、スコープの外では、見えないものと思ってしまいがちですが、そうなりません。
- サブルーチンの定義は、コンパイル時に、シンボルテーブルというものに登録されます。シンボルテーブルは、プログラムのどこからでも参照することができるため、サブルーチンも、プログラムのどこからでも参照できます。( スコープの影響を受けないということ )
と書いてるところをみると、1つのファイルスコープ内でパッケージに属するメソッドって書けないようにみえるがパッケージの場合は特別なんだろうか。
というわけでやってみる。
#!/usr/bin/perl use strict; use warnings; { package pkg; our $pkgour = 10; my $pkgmy = 20; sub pkgsub { print "$pkgmy\n"; } } print "main->pkgour:: $pkg::pkgour\n"; pkgsub();
C:\MyWorks\Perl\our>perl our4.pl Undefined subroutine &main::pkgsub called at our4.pl line 17. main->pkgour:: 10
ちゃんとエラーでた。
#!/usr/bin/perl use strict; use warnings; { package pkg; our $pkgour = 10; my $pkgmy = 20; sub pkgsub { print "$pkgmy\n"; } } print "main->pkgour:: $pkg::pkgour\n"; pkg->pkgsub();
C:\MyWorks\Perl\our>perl our4.pl main->pkgour:: 10 20
というわけで
http://d.hatena.ne.jp/yupug/20070222/1172172836
最初はこれ読んでまったく理解できなかったが概ね理解できた、と思う。