スコープ

PowerShell Coreで関数を扱い始めたからには、そろそろスコープについても理解しておかなければならない。スコープとはアクセスできる範囲のようなもの。入れ子構造を作ることもできる。アクセスできる範囲を限定的にして保護する機能だと思えばよい。

仮にスコープが存在しないプログラミング言語というものを考えてみると、変数や関数などをすべてユニークな名前にする必要があり、かなりコーディングが面倒なことになる。スコープを利用することで利用範囲を明確にすることができ、その範囲に限ったコーディングなどができるようになる。

PowerShellの関数は、基本的にその関数が作成された場所のスコープを継承する。PowerShellのスコープは主に次のようなルールに基づいている。

  • あるスコープ内で作成されたアイテムは、そのスコープの中からアクセスできるとともに、その子スコープからもアクセスできる
  • スコープを指定することで、デフォルトのスコープとは別のスコープに所属した状態で作成することができる


PowerShell Coreのスコープには分類がある。基本的に次の5つのスコープがあると考えておけばよいだろう。

スコープ 内容
グローバル PowerShellが起動されたときに効果を持つスコープ。PowerShellが起動したタイミングで作成される変数や関数はグローバルスコープに所属することになる。自動変数やプレファレンス変数がこのスコープに分類される。プロファイルに記述した変数やエイリアス、関数もグローバルスコープに所属する
ローカル 現在のスコープ。ローカルスコープはグローバルスコープやほかのスコープになることもできる
スクリプト スクリプトファイルが実行されるときのスコープ。スクリプトで動作するコマンドがスクリプトスコープに所属する。スクリプト内のコマンドにとっては、スクリプトスコープはローカルスコープということになる
プライベート プライベートスコープ内にあるアイテムに関してこのスコープ以外からはアクセスすることができない。ほかのスコープに存在しているのと同じ名前のアイテムもプライベートスコープの中であれば作成できる
番号付きスコープ スコープは名前のみならずスコープ間の相対関係を表す番号を使ってもアクセスすることができる。0はカレントスコープまたはローカルスコープ、1は親スコープ、2は親の親スコープ、といった具合になっている。番号付きスコープはスコープの入れ子を作っている場合に便利に使用できる

スコープはPowerShellインスタンスを起動するタイミング、セッションを作成するタイミング、関数やスクリプトを実行するタイミングで新しく作成されることになる。新しいスコープが作成された場合、もとのスコープとの関係は親子関係になり、もとの場所のスコープが親、新しく作成されたスコープが子という関係になる。

つまり、PowerShellではすべてのスコープの大元の親はグローバルスコープということになる。子スコープは親スコープから変数、エイリアス、関数を継承しないという特徴も備えている。また、スコープは明示的に指定することができ、その指定子はglocal、local、private、scriptとされている。

スコープを明示的に指定することもできる

スコープを明示的に変更することはあまりないかもしれないが、やり方は知っておいてもよいだろう。関数の場合、例えば関数名の前に次のようなスコープ指定子を付与すると、指定したスコープに所属する関数として作成することができる。

グローバルスコープで作成される関数

function global:関数名 {
    ...
    処理
    ...
}

PowerShell Coreのスコープは、汎用向けのプログラミング言語で採用されているスコープに似ているので、直感的に理解しやすいだろう。

PowerShell Coreのスコープを理解する場合には、シェルやシェルスクリプトのスコープとの違いを意識しておくとよいかもしれない。PowerShell Coreがインタラクティブシェルでの利用が想定されていることから、こうしたシェルとの違いを知っておくのは有益だ。

一番知っておきたいのは、シェルのスコープはちょっとトリッキーというか 、汎用目的で人気の高いプログラミング言語のスコープと比べると結構理解しにくいというか、シェルやプロセス生成の仕組みを知っていないと動作が意味不明な点が多いということだ。

シェルとPowerShell Coreが同じ管理目的のシェルとして使用できるという観点から同じようなものだろうと考えると、このあたりで大きな誤解が生まれることになる。

PowerShell Coreは管理用のインタラクティブシェルとしても利用できるようになっているものの、プログラミング言語としての側面はオブジェクト指向言語のそれに近い。スコープも人気の高いプログラミング言語のような仕組みになっているし。シェルやシェルスクリプトよりも直感的で理解しやすい。

一方、シェルのスコープは汎用目的のプログラミング言語から比較するとかなりトリッキーに映る。これは根幹的にはプロセスを生成するfork()という仕組みに依存しており、さらにはシェルが備えているサブシェルという機能が状況を理解しにくいものにしている。

シェルの連載ではないのでこのあたりの詳しい説明は省くが、シェルのスコープは汎用目的のプログラミング言語とは結構違っている、ということは覚えておいてほしい。

その点、PowerShell Coreのスコープはよく使われているプログラミング言語のスコープのように直感的に理解しやすいものなので、ちょっと使えば特徴は大枠で理解できるだろう。関数を作成して利用するようになってきたら、概念と仕組みをよく学んでほしい。

参考資料