1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

our: パッケージ変数へのエイリアスの宣言

Last updated at Posted at 2024-07-06

凄く今更。

こっちの記事を書いたついでに。our での検索上位を占めているページに思う所があったので書いとく。1

「〜な変数の宣言」と書かれた場合の一般的な受け取り方としては、「これこれこう言う機能を持った変数です、との宣言」として受けとるだろう。本稿もその前提で記載する。


主張

our の機能は、巷で良くタイトルにされる「パッケージ変数の宣言」ではない。2

our の機能は、該当レキシカルスコープ内で、「パッケージ変数へのエイリアスを宣言する」だけのものである。


つまり、our $h とすれば、そのパッケージのパッケージ変数(通常はmain なので $main::h )へのエイリアスを宣言し、パッケージ名 (main::) を省略可能にする。

それ以上でも以下でもない。


パッケージ変数の宣言

では、パッケージ変数の宣言は、どうするのか?

パッケージ変数($Foo::bar) は最初に使われたときにひょっこり現われる3 もので、完全に修飾された変数 4 である為、use strict のエラー対象外となるもの。そのため宣言は必要ない。

強いて言えばパッケージ名自体が宣言の様なものだ。

our $h がパッケージ変数の宣言と言われるのは、

  1. たまたま、$main::h を先に弄ってなくて、
  2. our $h を実行したと同時に $main::h がひょっこり現われた

だけ。

パッケージ変数に宣言は必要ない。(2回目)


no warnings; no strict; 時

改めて書くのもアレだが、no warnings; no strict; での(宣言無しの)新たな変数は全て、パッケージ変数($Foo::bar)だ。もっと言えば、our を省略した 5 パッケージ変数のエイリアス。

# no warnings, no strict の場合
% perl -le '$s = 10; print $main::s;' -M-warnings -M-strict
10

ついでに、 local について

パッケージ変数($Foo::bar)関係なので、localも取り上げる。

"local" はリストアップされた変数を、囲っているブロック、 ファイル、eval の中で、ローカルなものにします。6

で、変数関連と特長は、

  1. 事実上、パッケージ変数専用
  2. ダイナミックスコープ7を取る

である。

変数の相関関係で言うと

.
+-- パッケージ変数($Foo::bar)        # our でエイリアス作成可能
|    +-- local 変数
+-- my 変数
+-- state 変数

の様な形。

で、パッケージ変数専用と意識すると、local が ダイナミックスコープであるのは自明となる。

例文で書かれがちな ↓ の様な記載は、

#!/usr/bin/env perl
no strict;
no warnings;

sub test () { print $var . "\n";}

$var = 100;
test();
{
    local $var = 10; 
    test();
}
# output
# 100
# 10

パッケージ名を明記するだけで、レキシカルスコープであると考える事自体が、パッケージ変数の存在意義を否定してしまう事が分る。

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

sub test () {  
    # レキシカルスコープとしたら、ここで以下の様に直接書く事は出来ず
    # @_ 経由の引渡しが必要となってくる。
    # そうすると、パッケージ変数自体のメリットは皆無となってしまう。
    print $main::var . "\n"; 
}

$main::var = 100;
test();
{
    local $main::var = 10;
    test();
}
# output
# 100
# 10

再び、 our について

さて、our に戻り、多少の挙動例を記載して本稿を締める。

レキシカルスコープを跨いで複数回宣言するのはダメ。

% perl -le 'package test; $test::s = 10; our $s; { our $s; print $s; } print $s;' -Mstrict -Mwarnings
"our" variable $s redeclared at -e line 1.
	(Did you mean "local" instead of "our"?)
10
10

前の our のスコープが消滅してれば、our しても良い。

# OK: 跨いでないから 
% perl -le 'package test; $test::s = 10; { our $s; print $s; } our $s; print $s;' -Mstrict -Mwarnings
10
10

local した後に our しても、our した後に local しても OK8

% perl -le 'package test; $test::s = 10; { local $test::s = 100; our $s; print $s; } print $test::s; 1;' -Mstrict -Mwarnings
100
10

% perl -le 'package test; $test::s = 10; {  our $s; local $s = 100;  print $s; } print $test::s; 1;' -Mstrict -Mwarnings
100
10

  1. と言ってもこのページが検索上位に上る訳ではないだろうから、抑止にはならんだろうけど。もっと言えば、単なる自己満足

  2. もちろん、そのページの中身では、きちんと解説されている場合もある

  3. perldoc -f our より

  4. perldoc strict より。この訳語はどうかと思うが、要は UNIX のパスで言えばファイルへのフルパスに相当するのが、「完全に修飾された」という言葉。相対パスに相当するものはない。

  5. もちろん、実装時系列的には正しい説明ではない

  6. perldoc -f local より

  7. perldoc perlfaq7参照

  8. local の説明を加えたのは、このワンライナーのため

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?