localを使うためのメモ

こないだourで、今回はlocalを使うためのメモ。

2013/09/15 追記
$a$bは特殊パッケージなので、
念のため、$a$fooに書き換えて確認しました。(*1)
— ここまで追記 —

ourはパッケージと関連付けられた変数ということで、
次はmyではなくlocal

use strict;
use warnings;
use v5.10;

our $foo = -1;
say $foo;
{
    local $foo = 'hello';
    say $foo;
    {
        local $foo = 0;
        say $foo;
    }
    say $foo;
}
say $foo;

実行するとこんな感じ。
$ perl aaa.pl
-1
hello
0
hello
-1

$aourを付けなくてもいいし、
ourの代わりにlocalを付けてもいんだけど、
myを付けるとエラーになる。
$ perl aaa.pl
Can't localize lexical variable $foo at aaa.pl line 8.

でも、localを使うケースは、
ourで宣言した変数に使う場合がほとんどだと思うので、
今回はourを付けることにする。

実行結果から分かるように、
{...}の中での変更は、{...}の中でだけ有効になるキーワードで、
これをローカル化と呼ぶらしい。
詳しくは、ここを見るのが良いと思う。

perlsub – Perl のサブルーチン – perldoc.jp

自分の解釈だと、localを使ったタイミングでコピーを棚の上に置いて、
localを使った{...}を抜けたら、棚から下ろして元に戻している。
なので、実行時のスコーピング(*2)とも呼ばれている。

例えば、こんな感じでファイルを配置する。

.
├── Foo.pm
├── aaa.pl
└── bbb.pl

“Foo.pm”はこんな感じ。

package Foo;
use strict;
use warnings;

our $foo = 1;

sub hello {
    return $foo;
}

1;

“aaa.pl”はこんな感じ。

use strict;
use warnings;
use v5.10;
use lib '.';

use Foo;

say 'Foo::hello() = ', Foo::hello();
bar();
say 'Foo::hello() = ', Foo::hello();

sub bar {
    $Foo::foo = 0;
    say 'Foo::hello() = ', Foo::hello();
}

sub bar {...}の中でパッケージFooの$aが書き換えられて、
以降でも影響が出てしまっている。
$ perl aaa.pl
Foo::hello() = 1
Foo::hello() = 0
Foo::hello() = 0

次は、”bbb.pl”の中身。

use strict;
use warnings;
use v5.10;
use lib '.';

use Foo;

say 'Foo::hello() = ', Foo::hello();
bar();
say 'Foo::hello() = ', Foo::hello();

sub bar {
    local $Foo::foo = 0;
    say 'Foo::hello() = ', Foo::hello();
}

これだと、sub bar {...}の中でのみ、挙動を変えることが出来る。
$ perl bbb.pl
Foo::hello() = 1
Foo::hello() = 0
Foo::hello() = 1

でもって、正直に告白すると、Log::Minimal(metacpan)を見て勉強しました。

おしまい。

(*1) akiymさん++
(*2) Effective Perl(AMAZON)より引用。

Leave a Comment