パーフェクトPHPのクロージャの説明が全然わからなかった
2週間PHPの勉強期間をもらえました。それからは業務+Railsの勉強期間。ありがたすぎます・・
— Hiromi Kimura (@kimromi) 2015, 7月 2
というありがたい環境の中で現在もっぱらパーフェクトPHPの書籍にて勉強させていただいてます。そのパーフェクトPHPの中でクロージャの説明がよくわからなかったです。
クロージャとは、関数内に現れる変数の名前解決が、ローカルスコープだけでなく関数が定義された場所のスコープも含めて行われる関数のことです。
???
よくわからなかったので調べてみても、「無名関数はクロージャとも呼ばれる」みたいなことが書いてあって、なんかちょっと違うような気がしました。そんな中で下のエントリがとてもわかりやすかったです。
要するに無名関数の中では無名関数の外の変数は見えないのでuse()で見えるようにしましょうということでしょうか。
<?php function method() { $hello = 'hello'; $closure = function() { echo "${hello}! world!", PHP_EOL; // Notice: Undefined variable: hello… }; $closure(); } method();
としても5行目の無名関数の中で$hello
が見えないので実行時エラーNotice: Undefined variable: hello…
になります。
そのため下のように引数で渡すようにもできます。
<?php function method() { $hello = 'hello'; $closure = function($greeting) { echo "${greeting}! world!", PHP_EOL; }; $closure($hello); // => hello! world! } method();
ただこれだと無名関数に渡したいものが増えた時に引数を増やしたりでメソッドの仕様が変わってしまうので、その時にuse()
を使えば便利ですよってことです。
<?php function method() { $hello = 'hello'; $closure = function() use ($hello){ echo "${hello}! world!", PHP_EOL; }; $closure(); // => hello! world! } method();
この場合のuse()
で渡す$hello
は値渡しなので無名関数内で書き換えても外側の$hello
は書き換えられません。
<?php function method() { $hello = 'hello'; $closure = function() use ($hello){ $hello = 'goodby'; echo "${hello}! world!", PHP_EOL; }; $closure(); // => goodby! world! echo $hello; // => hello } method();
無名関数の中で書き換えたい場合はuse()
で参照渡しができます。
<?php function method() { $hello = 'hello'; $closure = function() use (&$hello){ //参照渡し $hello = 'goodby'; echo "${hello}! world!", PHP_EOL; }; $closure(); // => goodby! world! echo $hello; // => goodby } method();
ということでOKかな!
ちなみにですがクロージャの概念を知るにはこれがわかりやすかったです!まさにuse()
でローカルスコープ外の変数を捉えるということですね。
その上でパーフェクトPHPで書いてる内容をみたら言ってることの意味がわかった。。要するにクロージャの概念が全くわかってなかったということでした。ちゃんちゃん。