GOTOコントロールキーワードがPHP 5.3.0で導入されたことを少し前に発見しました。
http://php.net/manual/en/control-structures.goto.php
なぜそれが起こったのですか?
この背後にある言語設計の目標は何ですか?
PHP開発者コミュニティはそれを求めましたか?
goto
。
GOTOコントロールキーワードがPHP 5.3.0で導入されたことを少し前に発見しました。
http://php.net/manual/en/control-structures.goto.php
なぜそれが起こったのですか?
この背後にある言語設計の目標は何ですか?
PHP開発者コミュニティはそれを求めましたか?
goto
。
回答:
責任者は、このブログ投稿にそれを追加する理由を示します。
[T]私が取り組んでいた(いつか戻ってくるかもしれない)プロジェクトは、プログラミング言語を知らなくても動的なWebサイトを作成するためのワークフローベースのサイトビルダー[…]でした。サイトの実行方法に関するすべてのメタ情報を作成し、次にサイトビルダーがそれを実際のサーバーで実行されるPHPコードに「コンパイル」します。
GOTOがなくても実行できますが、特に複雑なビジネスロジックの結果のロジックは、それを使用することではるかに簡単になります。
PHPの防御では、限定されたスコープ内のラベルにジャンプすることしかできません。これにより、実行できる害が制限されます。
(また、PHPがこれまでに発明されたすべてのプログラミング言語からのすべての構造を明らかに吸収している方法を考えると、追加goto
は単に避けられなかったと主張するかもしれません)
every construct from every programming language ever invented
!...無限の彼方へ!(そして、彼らがPerl 5についてこれまで言っていたものだと思うと... PHPと呼ばれるナンセンスのこの増え続ける小さな塊をとても誇りに思っています)
下位レベルのPHPではgoto
、PHP 4以降に使用されていました。PHP4では、インタープリターがやり直され、Zend Engineが導入されました。これには、低レベルの「オペコード」にコンパイルされ、エグゼキューターに渡されます。
そのレベルでは、ジャンプ操作がall if
、switch
または任意のループステートメントに使用されます。PHP 5.3ではgoto
、長い議論の後、という名前でエクスポートすることが決定されました。
主な理由は次のとおりです。
最初の2つの項目は説明を必要としない場合があり、3番目の部分は次のような状況に関するものです。
function do() {
$lock = $acquire_lock...)
if (!do_something()) {
goto cleanup
}
if (!do_more()) {
goto cleanup;
}
cleanup:
free_lock($lock);
もちろん、PHPにはそのような状況はほとんどありません。PHPには参照カウントガベージコレクションシステムがあり、そのような変数と関連リソースを予測どおりに解放します。それにもかかわらず、開発者がクリーンアップコードを複数回複製したり、エミュレーションとしてd do { } while (0);
を悪用したりするような状況が存在break
しgoto
ます。
誤用を防ぐために、ループにジャンプできないように実装が制限されていました。したがって、有名なDuff's Deviceの邪魔をすることはできません。
結局のところ、PHPは問題を解決するために開発されています。自分の足で撃つことから完全に保護するわけではありませんgoto
。この制限よりも悪い方法で多くの機能を悪用することができます。したがって、結論は、それが有用で問題を解決できるエッジケースがあるということでした。
try-finally
構成を実装しないのはなぜですか?(PHPには1つありますか?)
finally
かなり最近になり、その後になりましたgoto
。
どんな言語でも悪いコードを書くことができます。goto
言語を使用しているからといって、言語が悪いというわけではありません。
さまざまな言語で既存の構造を考える- ブレーク、continue
、next
、最後に、throw
。でも、switch
これらは、スコープの同じまたはより高いレベルへのスコープの1つのレベルからその行くに計算され、外出先のすべての形態です。
gotoの問題は、それがより深いレベルのスコープに入るとき、またはスタックフレームをジャンプするときです。
質問からリンクされたドキュメントの例3に注意してください。
<?php
goto loop;
for($i=0,$j=50; $i<100; $i++) {
while($j--) {
loop:
}
}
echo "$i = $i";
?>
goto
はより深いレベルのスコープにジャンプしようとしているため、これは機能しません。
さまざまな形式の制限付きgotoには何の問題もありません。gotoという名前のキーワードや他の分岐名があります。代替案(forループの醜い条件文)は、多くの場合より悪い場合があります。そのまま、gotoを使用すると、
個人的には、例1の例が気に入らない
<?php
goto a;
echo 'Foo';
a:
echo 'Bar';
?>
ただし、これは、このようなコードを意図的に作成する開発者に何らかの体型学習経験を適用する必要があること以外は、言語に問題を引き起こしません。
goto
ソースを読むことに慣れているかどうかに関係なく、良い使い方があります。それらが慣用的なコードで頻繁に見られるかどうかは別の問題です。しかし、後藤は害を引き起こしません。