謎の演算子

PHPへのオペレータ追加続き

$ php -r '$users ||= "john"; echo $users[0];'
john

おお!!!!!!

var_dumpで確認
$ php -r '$users ||= "john"; var_dump($users); '
array(1) {
  [0]=>
  &string(4) "john"
}

え。文字列リテラルへの参照ってなに!?

数値を…
$ php -r '$users ||= 20070602; var_dump($users); '
array(1) {
  [0]=>
  &int(20070602)
}

え?え??

動作確認用のスクリプトを作成。wktk

push.php

<?php
$arr = array();
for ($i = 0; $i < 5; $i++)
{
    $arr ||= $i;
}
var_dump($arr);
$i = 100; // 書き換えてみる
var_dump($arr);
?>
出力
 $ php push.php
array(5) {
  [0]=>
  int(5)
  [1]=>
  int(5)
  [2]=>
  int(5)
  [3]=>
  int(5)
  [4]=>
  int(5)
}
array(5) {
  [0]=>
  int(100)
  [1]=>
  int(100)
  [2]=>
  int(100)
  [3]=>
  int(100)
  [4]=>
  int(100)
}

名付けてリファレンスプッシュ演算子

  • $users[] = 'john';
  • $users ||= 'john';

を比較した場合、の存在が大きな違いになってくる。の存在が$usersを配列と解釈して処理を実行していってくれるのですが、が無いということで、||=演算子側で左辺値$usersにがあるように見せるような実装をしなきゃいけない。

最初はガンガンと、opcodeを読んでゴチャゴチャ実装してたのですが、segmentation faultやら見たこと無いようなエラーが沢山出るので、一旦リセット。
考えをシンプルにして、左辺値をconvert_to_array_ex()で配列に変換し、右辺値をadd_next_index_zval()で突っ込んでみたら、上記の参照状態での挿入になりました。

いやぁ、奥が深い。まだまだわからないことだらけです。いろいろと勉強になりますね。
実装コードはまとまればそのうち…。

$users[] ||= 'john'で配列に代入!みたいな既存のルールに沿うような演算子なら結構簡単に作れるかもしれないです。

あ。あとこんな感じに離して書けるんですね。しらなかった。

$users      []= 'john';