単語記事: goto

編集  

gotoとはプログラミング言語に今も残る因習の一つである。古の昔、この機の是非をめぐって大論争が起きた事で悪名高い。歴史上幾度となく殺されかけたが未だにしぶとく生き延びている。単純な生物は強い。

概要:

古典的なgotoは、その名の通り「あそこの(あのラベルの)処理に飛べ!」という単純明解な機である。ラベルが書ければどこにでも飛べる上にデフォルトでは戻ってこない

サポートする言にはFORTRAN, BASIC, C(当然C++)と、メジャー古参高級言が名を連ねており、いかにも「由緒正しきスタンダードな機です」感が漂うが、基本的にgotoに頼る設計はダサいとされている。

gotoの何がいけないか:

関数呼び出しと違って原則として元に戻ってこないので、プログラムの構造をぶっちぎって構造化プログラミングを台しにすることができる。ある意味構造化プログラミング敵ともいえる。

状況によっては特定の処理を飛ばす事も容易に行えてしまう。たとえば、「ファイルを開き、データ読み込み、ファイルを閉じる」という処理があった時、「データ読み込む」処理にgotoが入っていて、gotoで飛んだ先から「ファイルを閉じる」処理に戻ってくるように書くのを忘れてしまうと、ファイルが開いたままになってしまうのである。

また、安易なgotoの多用は絡まり合うような処理の流れを生み、本人ですら処理の流れを把握することが困難なソースコードを作り出す。絡まり合っていることからスパゲティコードと呼ばれる。

あった方がいいのか、ない方がいいのか:

まあ実際goto賛成の言い分も一理あり、高級な文法で大げさな事を書くより「こんなのgoto一発だろ」という場面があるのは事実。最後に物を言うのが職人先なのはどこの世界も一緒である。思想的に正かろうと動くものを作らなければ始まらない。

しかしながら、人は過ちを犯す生き物である。くれぐれも自分の足を撃たないように注意して使うべし。

……というあたりで、必要と感じる人と捨てるべきだと感じる人の間で論争になったりする。

論争の本質:

gotoがないよりはあったほうがプログラムを書くときに便利だが、弊が生じやすい」という点ではおそらく全員意見が一致している。

賛否が別れるのは、一つの問題点を、優先するものの違う2つの立場から捉えているからに過ぎない。すなわち、

  • goto肯定:
    • やれることの選択肢は広い方がよく、弊を生じるような使い方をしなければよい。
    • が生じたとしたらそれは使った者の責任であり、言仕様責任ではない。
  • goto否定:
    • 使えなければ、使用による弊が起き得ないから、多少不便でも言仕様の段階で使えないようにしよう。
    • 自分が注意していても他のかがやらかす性もあり、それを防ぐのも言仕様責任である。

という立場である。

もっとも、近年のプログラミング言語の傾向としては(優秀なプログラマーからそうでない者まで)大人数で安全な開発を行えるようにすることを重視するという考えが流なので、今時の言古典的意味でのgotoを採用することはまずない。

GoD言語は"goto"を採用しているが、表記こそ"goto"であるものの、後述のように用途制限により実質的には"古典的gotoの代替"と同種のものとなっており、この記事で議論している古典gotoとは本質的に異なるものであり関係である。

議論がかみ合わない点:

概要で述べたように、gotoはどこにでも飛ぶことが出来る一方で戻ってくることが保されないために、注意しないと構造化プログラミングを破壊してしまうことが問題なのである。

逆にいうと、goto使用もプログラムの構造を破壊しない限りにおいては構造化プログラミング上の問題を生じない。gotoを使うことが「必ず」問題を引き起こすというわけではないのである。goto文字列をにした途端に思考停止してアンチパターンだと糾弾するのはいいことではない。

一方で、gotoを否定する議論では、goto使用による弊という「結果」のみを問題にしているわけではない。「gotoが存在すること」によって弊のある使い方が「出来てしまう」こと自体が問題視されているのである。従って、弊を起こさないように上手に使いさえすればよいというgoto肯定の反論も的を射ていない。可能性を生み出しただけでアウトなんだよ

また、gotoを適切に用いれば構造化プログラミング上は問題ないといっても、コード中にgotoが存在するだけで、そのgotoの適切性を検証しなければならないという管理上の問題が生じる。この場合、gotoを利用している単位での品質管理が重要で、継続してテストコードが書かれ検証されるようにすることであらかじめ問題を検知しておきたい。

そのような環境が整わないのであれば、やはり、gotoが使用可な言であっても使用しないほうがよいだろう。例外があるとしたら、コメントなどで適切性を簡潔に明できる場合や、達人が自分一人プログラミングする場合くらいであると思われる。

古典的gotoの代替:

構造化定理により、gotoを用いた処理を反復・分岐などの組み合わせに書き換えることは理論上可であるが、その書き換えを行うことが性可読性について不利になるケースも希にある。

この点に対して、多くのプログラミング言語gotoより限定された範囲でのジャンプ制御命令(break, continue, exception...など)を用意することで解決策を提供している。

これらの命令はジャンプ制御を行うという点においては基本的にgotoと同義である。その代わり、ジャンプできる先を制限し、最終的に本来の処理の流れに戻ってくることを保することにより、複雑なプログラムフローとならないように言レベルでの制限(あるいは構造化プログラミングの補助)を行っている。

古典的gotoの代替としての"goto"

先述のように、新しい言でも"goto"を採用している言はある。しかし、これらの"goto"は使用方法がプログラムの構造を破壊しないように制限されており、古典gotoに関する議論とは関係のないものである。

D言語

D言語の"goto"はC言語と同様にジャンプ先のラベルが、同じ関数の内部からしか参照できないようになっている。また、"goto"があってもfinally節の実行は回避されないtry-catch-finally構文が用意されている。

これにより、関数の処理から抜けた時には元の流れに戻ることが保される。また、飛ばされると困る処理はfinally節に書くことで確実に実行されるようにすることができる。

Go言語

Goでも"goto"が採用されているが、ジャンプ先に制限がある。ブロック構造の外側に飛ぶことができないようになっており、内側のブロックに飛んでも、内側のブロックから抜け出したときに元のブロックの処理の流れに戻ってくることが保されるようになっている。

GOTO 関連動画

GOTO 関連項目


【スポンサーリンク】

携帯版URL:
http://dic.nicomoba.jp/k/a/goto
ページ番号: 4630852 リビジョン番号: 2444956
読み:ゴートゥ
初版作成日: 11/05/11 23:47 ◆ 最終更新日: 17/01/04 07:43
編集内容についての説明/コメント: gotoの使用の有無に関わらない一文を除外
記事編集 / 編集履歴を閲覧
このエントリーをはてなブックマークに追加

この記事の掲示板に最近描かれたお絵カキコ

お絵カキコがありません

この記事の掲示板に最近投稿されたピコカキコ

ピコカキコがありません

gotoについて語るスレ

13 : ななしのよっしん :2014/06/08(日) 12:57:59 ID: TUj4MW/5Df
batgotoswitchみたいなもんだよな
14 : ななしのよっしん :2014/11/29(土) 16:34:54 ID: CshybwZmkX
多重ループ脱出にはどうしても使う
15 : ななしのよっしん :2015/03/27(金) 03:24:32 ID: Fci0QEjqgY
 元記事の内容を保存しようとしたまま再構成してるので見出しとその中の記述が噛み合っていません。

 具体的には

goto肯定」の中に
しかしながら、人は過ちを犯す生き物である。くれぐれも自分の足を撃たないように注意して使うべし。」が現れるのはおかしいです。


「論争の本質」は
「言仕様で安全にしておくべきか?」であって、古典gotoは関係ありません。
 と言うか古典gotoって何でしょうか。D言語の例がありますが、C言語であったとしてもgoto関数えて移動することはできません。
(setjmp関数, longjmp関数ならありますが)
(省略しています。全て読むにはこのリンクをクリック!)
16 : ななしのよっしん :2015/05/06(水) 19:57:38 ID: IkEmbO96hw
>>14
多重ループしていても全ループを脱する命令が用意されている言もあるし、
関数などにしてしまえばループが単純化できるケースも散見されるのも事実
17 : ななしのよっしん :2015/05/29(金) 12:37:12 ID: h8t/dAIoBw
条件的ジャンプ権は内閣により閣議決定されました
18 : ななしのよっしん :2015/11/20(金) 09:45:28 ID: mT1ingmRrQ
Goto is god
19 : ななしのよっしん :2016/02/27(土) 23:24:06 ID: 78weVXldaj
まぁ上に飛ばなければそんなに問題はないんじゃね?

それかINTERCALとかにあるcomefromを使うか…
しかもある実装によるとラベルに対応するcomefromが複数あるとそのラベルに達した時点で複数のスレッドが生成されて行して実行を続けるという…
20 : ななしのよっしん :2016/06/13(月) 14:52:02 ID: yQ7vCGP5L0
ここまで後藤なし
21 : ななしのよっしん :2017/10/25(水) 23:06:24 ID: d3mqZgMYH1
goto検索して一番goto批判的なのが処の記事だった。
構造化を破壊するgotoが好ましくないだけで、例えば、

if(…) goto work_tail;

で処理ブロック丸々飛び越してネスト地獄を減らすのは、可読性においても有効な手なんだけど、それを引き継いだ馬鹿が何でもかんでもgotoを乱用する可性が怖いので、わかってる人たちだけで使いましょうねってことだよね?
記事を書いた人は何が何でもgoto全否定義者なようで、ああこの人は日常においてもtruefalseの二択なんだな~と思わずにはいられない。
22 : ななしのよっしん :2017/10/25(水) 23:23:55 ID: d3mqZgMYH1
ちなみに良心的gotoについては、近代の高級言であれば、witch-caseや例外、ラベル付きbreakなどの代替処理命令が存在しますが、
逆に言えば、肯定と否定はじつは同じコーディングスタイルの命令名の付け方で対立しているに過ぎないという言い方もできます。
良心的gotoに準じる命令は使っても良いというお付きですね。
lintでも、以前は機械的にgotoを排除していましたが、最近は良心的gotoに限り、使用を許すようになりました。
ニコニコニューストピックス
電ファミwiki
  JASRAC許諾番号: 9013388001Y45123
  NexTone許諾番号: ID000001829