1. ホーム
  2. スクリプト・コラム
  3. パール

perlにおけるmyとourの違いの解析

2022-01-29 08:32:10

perlにおけるourの使用法
require 5.006
バージョン番号が 5.006 未満の場合、モジュールのロードに失敗し、失敗が返されます。
つまり、何をしているかというと、モジュールの呼び出し環境のPerlのバージョンを確認しているのです。

ourは、myと同じく、変数の宣言で
が、ourはパッケージのグローバル変数を宣言しています。
で、my はレキシカル変数を宣言しています。

しかし、私たちが宣言した変数では、次のようなレキシカル変数のようになります。
実はこれが私たちの存在意義であり、ストリクト・プラグマを騙して、レキシカル変数ではないのにレキシカル変数であると思わせるためです。

私たちのことを簡単に理解する方法があります。
1、ourで宣言された変数をmyで宣言された変数と同じように扱うだけです。
2, ourとmyの違いを覚えておいてください。ourはパッケージのグローバル変数を宣言しているので、シンボルテーブルに格納されます(完全修飾でどこでもアクセス可能)、一方myは真のレキシカル変数を宣言しているのでクロージャブロックの中だけでアクセス可能です。

コード例

コピーコード コードは以下の通りです。

my $var = 1;

{
    my $var = 2;
    print $var, "\n";
}

print $var, "\n";

出力します。

2

1

コピーコード コードは以下の通りです。

our $var = 1;

{
    our $var = 2;
    print $var, "\n";
}

print $var, "\n";

出力します。

2

2
perlにおけるourの使用法
実は、ourの出現にはそれなりの歴史がある。
Perlは他の言語と違い、変数を何度でも宣言することができます。
Perl 4の時代には、マイとか必要なかったんですけどね。
名前を書くだけで、変数になる。
これはPerl5でも同じです。my で明示的にレキシカル変数として宣言しない限り、すべての変数は(パッケージ)グローバル変数であり、宣言なしで直接使用することができます。
しかし、これは誤って間違った名前を書いてしまったり、記号参照を解くときに文字列演算を間違えると大変なことになるという欠点があります(Perl 5の構文によれば、これらは正しく、結果は新しい変数になるので、明らかにやりたいこととは違うのですが......)。

そこで、これらの問題を解決するために、Perl5ではstrictとwarningsというプラグマが導入され、その内容、つまり宣言なしに変数が直接使われることを制限するものですが
だから、グローバル変数は使えないのです(注1)。
私たちの機能は、グローバル変数を宣言することですが、strictとwarningにレキシカル変数と思わせて、私たちの宣言した変数もレキシカルスコープされます。しかし、実際にはグローバル変数なのです。

注1.
ourを使用しない場合、グローバル変数を作成する方法は2つあります。
1, no strict "vars" を使って一時的にstrictプラグマをオフにし、宣言した後に use strict "vars" を使ってオンにします。
2, $main::varや$foo::barのように、変数の完全修飾名を使用する。

------------------------------------------------------------------------------------

使用
パッケージ
当社
この3つの間には何の関係もありません。

は、.pm ファイルを読み込んでいます。
パッケージは、現在の名前空間を切り替えるために
ourは、現在の名前空間に変数を作成することであり、変数がすでに存在する場合は、ourは宣言としてのみ機能します。

------------------------------------------------------------------------------------

私たちの(または修飾子なしの)宣言は "パッケージグローバル変数" で、これは "package" に "depend" して、"パッケージ記号テーブル" に保存されています。
my は "lexical variable" を宣言します。この変数は "block" に依存し、 "block" に格納されます。この lexical variable はブロック外からアクセスできません(参照を渡す場合は除く)。
しかし、ラップされたグローバル変数は別物で、完全な資格でアクセスすることができます。