W.I.S. Laboratory
menu-bar

PHP


PHPは「関数≠クロージャ」「無名関数=クロージャ」となっている

JavaScriptはすべての関数がクロージャとなるので、関数内に関数を書いても、内側関数から外側関数のローカル変数にアクセスできる。(かのように見える)
そのため直感的なコードを書くことが可能になっている。
こういう仕組みをクロージャという。
PHPは関数内関数は書けるものの、関数がクロージャになれない。
内側関数から外側関数のローカル変数にはアクセスできないので、直感とは反した感じになる。

しかし無名関数はクロージャになっているので、無名関数を作成したスコープ内のローカル変数にアクセスすることができる。

ただ、無名関数を定義するときに外側関数の引数 $x をuseしないとアクセスできない。
これはPHPが変数の宣言子を持っていない(使い始めたところで宣言されたものとして扱う)ためだと思われる。
PHPのインタプリタは、$xが「無名関数内で使い始めたローカル変数」なのか、「外側関数のローカル変数へのアクセス」なのかを区別できない。
こういう場合、

  1. 外側スコープと同じ変数名は外側スコープのものとして認識し、それ以外の変数名はローカル変数として認識する
  2. 値を代入しなければ外側スコープの変数として認識し、値を代入した時点でローカル変数として認識する
  3. 外側スコープ変数へのアクセス時は変数名のプリフィックスを変える(例えば、$$x と書くと外側スコープの $x として認識するなど)
  4. 原則として外側スコープの変数として認識し、無名関数先頭で「local $x」などと書いたものだけローカル変数として認識する
  5. 原則としてローカル変数として認識し、無名関数に渡されたものだけ外側スコープの変数として認識する
など、いろいろな実装が考えられるが、PHPは5番の方法を採用したというわけなのだろう。
なのでPHPの use 命令は、C++のラムダ式でいう [=] や [&] (キャプチャ)とは違うようだ。(そもそもクロージャなのだからキャプチャ機能はいらない)
どちらかというと普通の関数からグローバル変数にアクセスするための global 命令に近いものだと思う。
useには値渡しと参照渡しがあるが、参照渡しのほうがJavaScriptのクロージャの感覚に近く、無名関数を返した先でも値が保持され、それが変更できる。


[ 戻る ]
saluteweb