ちょっとまったour

http://www.geocities.jp/ky_webid/perl5/025.html

○our変数

my と local に続いて、our変数という変数を説明しておきます。Perl にはこの3つの変数が用意されています。

our変数自身は、レキシカルスコープを持ちます。この変数は、他の変数のスコープが内側にあろうとも、必ず外側にある変数をアクセスしようとします。


#!C:/Perl/bin/perl

use strict;
use warnings;


my $num = 500;

function();
print "$num\n";   # 500 を出力




sub function{
    my $num = 100;

    # ここに新しいスコープを作る
    {
        our $num = 200;    # 一番外側にある $num に 200 を代入
        print "$num\n";    # 200 を出力
    }
    
    print "$num\n";  # 100 を出力
}


出力結果は次のようになります。

200
100
500


function関数の内部に、{ } を使って新しいスコープを定義しています。こういう手段を使うことは可能です。この中で our変数を使っています。

our 変数は、一番外側にある変数を隠してしまうような、別の同名変数を無視して、外側の変数にアクセスできるようにします。関数の外に $num があり、function関数の先頭にも $num があるので、普通なら、内側にある $num しかアクセスできないはずですが、our変数を使えば、外側の $num を触れるという訳です。

ここで注意して見て欲しいのは、出力結果の最後に 500 があることです。our変数を使って、一番外側の $num に 200 を代入したはずですが、最後には 500 に戻っていることが分かります。これは、our変数自身がレキシカルスコープを持っているためです。our変数のスコープを抜けたとき、外側の $num の値は元に戻ります。

これ読んだらよくわかんなくなった。
この場合のスコープの中のourってmainパッケージ?

http://d.hatena.ne.jp/yupug/20070222/1172172836

([意]訳)
"my"は、変数( $a )のためにメモリに領域を確保し、
変数( $a )がその領域を指し示すよう割り当てておくが、
"our"は、現在のパッケージのパッケージ変数( $Foo::a )を、
変数( $a )が指し示すように割り当てる。

つまり、 "our"はレキスカルスコープであるという点は"my"と同じであるが、
かならずしも、変数を新たに作るわけではない。

ということは、さっきの例でいえば

        our $num = 200;    # 一番外側にある $num に 200 を代入

これは

my $num = 500;

こいつじゃなくて、mainパッケージにレキシカルな$numを作ってそれに200をセットしてourがそのレキシカルな$numを参照してるよ、ってことじゃないのかなあ。
というわけでやってみる。

#!/usr/bin/perl
use strict;
use warnings;


my $num = 500;

function();
print "$num\n";   # 500 を出力

print "scope out $main::num\n";



sub function{
    my $num = 100;

    # ここに新しいスコープを作る
    {
        print "scope in $main::num\n";
        our $num = 200;        # 一番外側にある $num に 200 を代入
        print "$num\n";        # 200 を出力
    }
    
    print "$num\n";  # 100 を出力
}
C:\MyWorks\Perl\our>perl our5.pl
Use of uninitialized value in concatenation (.) or string at our5.pl line 20.
scope in
200
100
500
scope out 200

あってた(多分)
復習すると

#!/usr/bin/perl
use strict;
use warnings;


# ローカル変数
my $num = 500;

function();

# ローカル変数の$num
print "$num\n";   # 500 を出力

# パッケージ変数はまだ生きてる
print "scope out $main::num\n";



sub function{

    # subの中のローカル変数
    my $num = 100;

    # ここに新しいスコープを作る
    {
        # この時点ではourしてないのでパッケージ変数がない
        print "scope in $main::num\n";

        # mainパッケージに$numのパッケージ変数作成
        our $num = 200;        # 一番外側にある $num に 200 を代入

        # パッケージ変数を表示
        print "$num\n";        # 200 を出力
    }
    # スコープを抜けたので完全修飾名なしでパッケージ変数は使えなくなる
    
    # ここはsubのローカル変数
    print "$num\n";  # 100 を出力
}

ということだと理解したけどどうだろう。