Ranvis Script

Ranvis Script > Perl/PHP > 備忘録

スコープの違い

PHPはあまりマトモなスコープは持っていないので、変数に適当な名前を付けると見つけにくいバグが入り込んでしまうことがある。

# Perl
foreach $value (@array1)
    { ... }
# foreachで使った$valueは無効になっている
foreach $value (@array2)
    { ... }
// PHP
foreach ($array1 as &$value) // $array1を変更するためにリファレンスを使用
    ...
// foreachで使った$valueはまだ有効
foreach ($array2 as $value) // $valueは$array1の最後の要素のリファレンス
    ...
// 結果、$array1の最後の要素が二番目のループで変更されてしまう

これを回避するのにはunset()が使える。(但しあまり美しくない)

// PHP
foreach ($array1 as &$value)
    ...
unset($value); // 明示的に無効化する
foreach ($array2 as $value)
    ...

条件演算子の違い

PHPでは条件演算子の結合がPerlとは異なる。

printf('%s ', 1 ? 1 ? 'A' : 'B' : 'C');
printf('%s ', 1 ? 0 ? 'A' : 'B' : 'C');
printf('%s ', 0 ? 1 ? 'A' : 'B' : 'C');
printf('%s' , 0 ? 0 ? 'A' : 'B' : 'C');
# Perl
A B C C
// PHP
A B C C

ifの入れ子に相当する書き方はOK。しかし、

printf('%s ', 1 ? 'A' : 1 ? 'B' : 'C');
printf('%s ', 1 ? 'A' : 0 ? 'B' : 'C');
printf('%s ', 0 ? 'A' : 1 ? 'B' : 'C');
printf('%s' , 0 ? 'A' : 0 ? 'B' : 'C');
# Perl
A A B C
// PHP
B B B C

このようにelse ifに相当する書き方をするとPerl(Cもそうだが)とは異なった結果になってしまう。

普通の感覚では、

printf('%s ', 1 ? 'A' : (1 ? 'B' : 'C'));
printf('%s ', 1 ? 'A' : (0 ? 'B' : 'C'));
printf('%s ', 0 ? 'A' : (1 ? 'B' : 'C'));
printf('%s' , 0 ? 'A' : (0 ? 'B' : 'C'));

という結合を期待すると思うが、結果から

printf('%s ', (1 ? 'A' : 1) ? 'B' : 'C');
printf('%s ', (1 ? 'A' : 0) ? 'B' : 'C');
printf('%s ', (0 ? 'A' : 1) ? 'B' : 'C');
printf('%s' , (0 ? 'A' : 0) ? 'B' : 'C');

と評価されていることが分かる。(左結合?)

PHPでは条件演算子はifの代わりではなく、あくまでも演算子ということか。