PHPのVLDで関数を見るの記事で、PHPの関数の処理をVLDで見てみた。

C言語やGoのようなmain関数から始まる言語とは異なり、PHPはいきなり書き始められる言語では、他言語のmain関数の箇所でfunction nameがnullとして処理が開始していた。


VLDで関数のオペコードを見た時、無名関数だとどうなるのだろう?と気になったので、今回は無名関数で試してみる。

無名関数に関しては、


picture_large978-4-87311-697-6


オライリーから出版されているアンダースタンディングコンピューティション 単純な機械から不可能なプログラムまでの計算と計算可能性のラムダ計算の章がオススメ。

と本の紹介はここまでにしておいて、PHPで無名関数のコードを書いてみる。


lambda.php

<?php
$isEven = function($n){
        return ($n % 2 === 0);
};

if($isEven(2)){
        echo "even";
}else{
        echo "odd";
}

上記のような感じで、無名関数の処理を$isEven変数に格納して、if文内の式で作成した関数を実行してみる。

lambda.phpのVLDの結果は下記の通り

<$ php -d vld.active=1 -d vld.execute=0 /path/to/dir/lambda.php
Finding entry points
Branch analysis from position: 0
2 jumps found. (Code = 43) Position 1 = 6, Position 2 = 8
Branch analysis from position: 6
1 jumps found. (Code = 42) Position 1 = 9
Branch analysis from position: 9
1 jumps found. (Code = 62) Position 1 = -2
Branch analysis from position: 8
1 jumps found. (Code = 62) Position 1 = -2
filename:       /path/to/dir/lambda.php
function name:  (null)
number of ops:  10
compiled vars:  !0 = $isEven
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
    2     0  E >   DECLARE_LAMBDA_FUNCTION                                  '%00%7Bclosure%7D%2Fpath%2Fto%2Fdir%2Flambda.php%3A2%240'
    4     1        ASSIGN                                                   !0, ~1
    6     2        INIT_DYNAMIC_CALL                                        !0
          3        SEND_VAL_EX                                              2
          4        DO_FCALL                                      0  $3      
          5      > JMPZ                                                     $3, ->8
    7     6    >   ECHO                                                     'even'
          7      > JMP                                                      ->9
    9     8    >   ECHO                                                     'odd'
   11     9    > > RETURN                                                   1

branch: #  0; line:     2-    6; sop:     0; eop:     5; out0:   6; out1:   8
branch: #  6; line:     7-    7; sop:     6; eop:     7; out0:   9
branch: #  8; line:     9-   11; sop:     8; eop:     8; out0:   9
branch: #  9; line:    11-   11; sop:     9; eop:     9; out0:  -2; out1:  -2
path #1: 0, 6, 9, 
path #2: 0, 8, 9, 
Function %00%7Bclosure%7D%2Fpath%2Fto%2Fdir%2Flambda.php%3A2%240:
Finding entry points
Branch analysis from position: 0
1 jumps found. (Code = 62) Position 1 = -2
filename:       /path/to/dir/lambda.php
function name:  {closure}
number of ops:  5
compiled vars:  !0 = $n
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
    2     0  E >   RECV                                             !0      
    3     1        MOD                                              ~1      !0, 2
          2        IS_IDENTICAL                                     ~2      ~1, 0
          3      > RETURN                                                   ~2
    4     4*     > RETURN                                                   null

branch: #  0; line:     2-    4; sop:     0; eop:     4
path #1: 0, 
End of function %00%7Bclosure%7D%2Fpath%2Fto%2Fdir%2Flambda.php%3A2%240

通常の関数と異なる点として、function nameがclosure(クロージャ)になっていた。

クロージャは無名関数を扱う上で大切な考え方になるが、長くなるのでこの場では触れない事にする。

PHP: 無名関数 - Manual


無名関数は関数の実行結果ではなく、関数そのものを変数に格納して、後に実行することができる機能であって、この機能だからこそで気になることがあるが、それは次回の記事に触れることにする。