2018/12/30 php,無名関数、クロージャー、など パート1

無名関数・クロージャーについてまとめる。

記事内の青文字部分は根拠のはっきりしないブログ主の推測です。

青文字部分に限らず記事内の内容全てについて正確性を保証できません(笑)

「内容が違う」「このサイト、この本見ればわかるよ」みたいなのがあればお願いします。

まず無名関数、ラムダ関数について。


$message = ‘testestテスト’;

$example=function($para){
var_dump($para);
};
$example($message);   //testtestテスト

$message=’worldworldワールド’;

$example($message);  //”worldworldワールド”


↑これも無名関数というんだと思う。





次にuseを使って外のスコープの変数(グローバル変数)を引き継ぐ方法(値渡し)


$message = ‘testてすと&テスト’;
$example = function () use ($message) {
var_dump($message);
};
$example();  //string(25) “testてすと&テスト”

$message = ‘worldわーるど&ワールド’;
$example();  //string(25) “testてすと&テスト”


↑ useを使ってグローバル変数を引き継いだ場合、無名関数を定義した時点での$messageの値を表示する。

その後$messageの値を’worldわーるど&ワールド’に変えても、$example()を実行した結果はstring(25) “testてすと&テスト”。





$message = ‘testestテスト’;

$example = function () use ($message) {
var_dump($message);
$message=’クロージャ内で文字列を変更。’;
};
$example();
echo ‘<br>’;
echo $message;
echo ‘<br>’;
// 引き継がれた変数の値は、関数が定義された時点のものであり、
// 関数が呼ばれた時点のものではありません
$message = ‘worldworldワールド’;
$example();
echo ‘<br>’;
echo $message;
echo ‘<br>’;

//結果

//string(16) “testestテスト” 
//testestテスト
//string(16) “testestテスト” 
//worldworldワールド


↑ただ、値渡しでuseでグローバル変数を引き継いでいるので、無名関数内で$messageの値を変更しても、グローバル変数$messageの値は”testestテスト” のまま。(グローバル変数の値は$example()を実行した後も’クロージャ内で文字列を変更。’には変わっていない。)

推測だが、ラムダ関数でなく普通に関数宣言して関数実行した時は関数実行終了時に関数シンボルテーブルも消えるのではないか。ラムダ関数なので関数シンボルテーブルが消えずに’testestテスト’を指している。

そしてグローバル変数の値を ‘worldworldワールド’に変えても、関数シンボルテーブルが指しているのは’testestテスト’のまま。だから

二回目の$example();の結果も”testestテスト”





$message = ‘testestテスト’;

$example = function () use (&$message) {
var_dump($message);
$message=’クロージャ内で文字列を変更。’;
};
$example();
echo ‘<br>’;
echo $message;
echo ‘<br>’;

$message = ‘worldworldワールド’;
$example();
echo ‘<br>’;
echo $message;
echo ‘<br>’;

//結果

//string(16) “testestテスト”
//クロージャ内で文字列を変更。
//string(22) “worldworldワールド”
//クロージャ内で文字列を変更。


↑参照渡しでuseを使ってグローバル変数を引き継いだ場合。

参照渡しなので最初の$example()実行時にグローバル変数$messageの値も

‘クロージャ内で文字列を変更。’

に変更される。

グローバル変数$messageの値を ’worldworldワールド’ に変えると関数シンボルテーブルも ’worldworldワールド’ を指す(参照渡しだから)

だから2回目の$example()実行時は ”worldworldワールド”  が表示される。





次にクロージャについて。

 

コメントを残す

メールアドレスが公開されることはありません。