PHPの「参照」は,参照とは似て非なる糞参照じゃなかったっけ

ポインタと思ってるわけじゃなくて,参照と思ってる人も苦労してるらしいよ.

うろ覚えなんだけど,

  • PHPで参照と言ってる奴は,JavaRubyC++やその他の言語で参照と呼ばれているとは別の挙動を示す変態参照.
  • しかもPHP4からPHP5になる時に,互換性のない仕様変更が入るという天変地異にみまわれて,PHPプログラマが悲鳴を上げた.

ってな話だったかと.


それ以上にこれ書いてる人って,ちゃんとプログラミングを勉強したことないんじゃないかなあ.特にPHP以外の言語には触れたこともない.

それもあって論理展開が破綻してるように見える.読んでて頭が痛くなってくる.

まず、PHPのarrayは「値」です。もちろん文字列も「値」です。値は値なんだけど、それはミュータブルです。PHPのarrayもしくは文字列の代入は、一見すると、ポインタを使わない大きなC構造体を代入するような感じになります。

参照型変数とインスタンスの区別さえついてないんじゃね?むしろPHPの配列はハッシュテーブルを包含するオブジェクトでは.*1 配列であって配列でない.

配列(他もそうだっけ)の代入ではかってにインスタンスがコピーされるので,とてもウザイ.


http://www.php.net/manual/ja/language.references.whatdo.php

http://b.hatena.ne.jp/entry/tanakahisateru.hatenablog.jp/entry/2013/12/12/012728

  • id:m_shige1979 最初のうちは&演算子で参照になることを理解するとC言語でのポインタと思っていたがなんかいろいろ探すと…あれ???ってなったから参照渡しは意識して使っていないな
  • id:kabisuke 実行速度とか内部の挙動とかが問題なんじゃなくて、代入演算子っぽいものを使ってるのに右辺に破壊的な変更が加えられる文法があるよってことが問題かな…まぁ、参照代入をルールで禁止すりゃいいんですけど。

そうそう.問題は言語仕様や実行モデルのほうで,コピーオンライトによる小手先の最適化は本質じゃないと思う.*2 *3


参照代入についてはPHP4だと広く使われていたから禁止するのは難しかったと思う.そのくせ「PHP5とPHP4とは高い互換性があるからコードの変更の必要はほとんどない」みたいな、嘘の宣伝をしちゃうのはPHP陣営の良くない所だと思う.とくに4から5への移行時期は地獄だったろうな.

  • id:te2u そもそも「配列」と言っていて、配列以上のことをやっている、出来てしまうことがわかりにくさを助長していると思う。/パフォーマンスに関しては、これに限らず「測ってみなければわからない」もの。

配列のようで配列でない.参照のようで参照じゃない.それがなにかと聞かれたら,PHPの糞仕様と答えるほかない.

パフォーマンス全体としてはたしかにそう.ただし「無駄なコピーを追加した方が,そうでない時より遅くなる」というようなことはあって,PHPではコピーオンライトをデフォルトで入れてまでもパフォーマンス低下を防がなければならないのもそのため.

  • id:Mono_Book 個人的にPHPってクソだなと一番思ったのはintのサイズ。32ビットと64ビットでintのサイズが違う。ここまでは許せる。だが勝手に浮動小数点になるな。

へえそうなのか.それはヒドイ.

  • id:J138 phpの参照渡しで余計にメモリ食うというのは知らんかった、勉強になった。/ intのサイズはそもそもCPU依存だからphp関係ないし

intのサイズはそういう問題じゃないと思う.

PHPはWeb専用言語として設計されているくせに,「intのサイズがハード依存」というC言語の悪い所をマネしているのが問題.何十年も前の言語から全く成長してない.Javaあたりはそういう過去の失敗からちゃんと学んで,プリミティブ型のサイズはハードウエアに依存しない.*4

  • id:syuu1228 この話題を説明するのにインタプリタの実装自身を解説しないのはどうしてなんだろう。いくらPHPのコードみたってどうにもならないじゃんこんなの:PHPが糞言語なのはどう考えても参照をポインタだと思っているお前らが
  • id:oktnzm ll系の記事でいちいち時計で測ってるのがうける。内部処理見てこちらは何ステップ/クロックであちらはあれぐらいなのでこっちのほうが早いのでございます。ってやればいいんじゃないですかね?
  • id:uccafort 「参照渡しをカジュアルにやるのが間違いなのです。」長々と書いてるけど結局結論的にはココだよなぁ。わかってやる場合もその必要性がどうしてもある場合だけだしなー。ただ全く皆無ってわけじゃないのがアレ

オブジェクト指向言語だと,基本が「参照」を渡すから.

PHPもV5からそうなるように修正されたよね?*5


「普通に参照を渡してるだけなのに,勝手にインスタンスをコピーすんじゃねえよボケが!」ってのがそもそもの問題.しかも参照が参照と似て非なるからさらに腹立つ.

  • id:rti7743 プログラマが余計なことを考えずに適当に書いたコードが、一番最適に動く、この空気を読むことをおせっかいと思う人には向かないし、便利だと思う人には最適だと思う。僕はそーゆーところが好きだけどw

むしろ逆で,プログラマが考えたように動かない言語の筆頭がPHP.


プログラムとはプログラマが書いたようにしか動かない.陽電子頭脳ロボットじゃあるまいし,空気なんて読まないし,真の意味での最適化も理論的に不可能.これを便利だと思うのは,最適化したコードを書くスキルがないからでは.

http://b.hatena.ne.jp/entry/ameblo.jp/nikko-inma/entry-11122429825.html

  • id:cknbstr こんな仕様にしてわかりにくくなること以上のメリットがあるのかw 配列の要素を参照化したスコープの配列のコピーに対してのみこの動きになるっぽい http://ideone.com/iZuBDI
  • id:n2sPHPは悪くない、自分らが何とかするよ」と空気を読みすぎるPHPerに、言語開発者側が「じゃあこっちも適当な言語仕様でいいんだ」と甘えた結果、いろいろ不幸な事になっているのでは、とブコメとか読んで思う。

PHPでは普通こんな書き方はしないから,そういうトラブルは起こらないはず」というのは,「PHPが糞言語なので,地雷を踏まないように注意しなければ大変なことになる」と同義だと思う.*6


「普通は書かない」ではなく「そういう書き方をすべきじゃない」というなら言語機能として削除すべき.たとえばGOTO文のように.*7

Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

Java™ Puzzlers: Traps, Pitfalls, and Corner Cases (English Edition)

Java™ Puzzlers: Traps, Pitfalls, and Corner Cases (English Edition)

*1:バージョンによって解釈が異なる可能性もあるからなお困る.

*2:その意味じゃ,HotSpotVMなんて,もっと広範囲な最適化を行ってるわけで.

*3: http://www.programming-magic.com/20080307090613/ に書いてあることが事実なら,こりゃわけわからんわ.C言語ライクな「参照渡し」の演算子だけど挙動が全く別.$bがポインタだったとしたら,$aに入るのは「(ポインタ変数)$b」へのポインタ.これ$bが「ポインタ型変数へのポインタのポインタの....のポインタ」でも変わらない.そしてPHPでは現実に非対称な予測しがたい挙動を示すしねえ.

*4:たしか「longやdoubleの上位32bitと下位32bitがアトミックとして扱えるか否か」という微妙な問題はあったりするが.

*5:その仕様変更が糞だったせいで死屍累々.だれが代入演算子の仕様を変更しろと言った.

*6:特にPHP4からPHP5に移行したときは,「PHP5はPHP4との互換性が高いので,変更する必要は少ない」とか言ってなかったか?しかし現実にはPHP4用のコードには「参照渡し」が多用されており,上記のようなトラブルの種は無数にあった.そのうちどれが危険でどれが安全か,果たして作った人以外に分かるだろうか.そして実際にトラブルになった時,並のPHPプログラマーにそれを修正できるだろうか?

*7:Cの関数ポインタ → オブジェクト指向言語というのも,そういう流れの一つだと思う.