goto文

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動先: 案内検索

プログラミング言語におけるgoto文(ゴートゥぶん、: goto statement)とは、手続き列中の指定された場所(専らラベルで指定される)に無条件にジャンプ(移動)する、という制御構造のひとつである「文 (プログラミング) 」である。古い文献などで "go to" と離していることもあるのは、英語の go to どこそこ、といったような言い回しとの類似のためでもあり、FORTRANではプログラム中の空白は基本的に無視されるので、goto でも go to でも同じだったからという理由もある(BASICにも、どちらも使えるようにしているものもある)。

概要[編集]

goto文は、それ単体では働きを持たせることはできず、必ずラベルか何かによって飛び先が必要である。飛び先のほうにcome fromという文を置き、飛ぶ元にラベルを置く、という「come from文」という(冗談半分[1]ではあるが)提案もある(en:COMEFROM。提案自体はジョークだが、同等の機能がある言語は実際にいくつかあり、プログラムの理論上の研究対象にもなっている)。機械語における分岐命令の一種である無条件分岐と、アセンブリ言語のラベルをそのまま手続き型プログラミングに持ち込んだものと言え、何らかの条件分岐との組み合わせによって、ループであるとか、コードブロックの飛び越しであるとかいったような機能の一部となることができる。

「以前に実行した場所に戻る」というループなのか、この先にあるコードは別の流れの一部なので「単に飛び越したいだけ」というジャンプなのか、という単純なことすら、goto文ではその見掛けからはわからない。if文while文と比較して考えれば、そういった「意図のあきらかでなさ」は明白であり、後述のように、if文やwhile文で単純に書けることであれば、gotoは使うべきではない。一方で、深く多重にネストしたループからの脱出など(そもそも、そのようなループ自体に問題があることもあるとは言え)、gotoを使ったほうが単純かつ明確に書ける場合もあり(Javaのラベル付きbreakなどは、ほぼ、そのような場合をgoto無しでも(Javaではgotoは使えない)書けるようにするためにある)教条的に排除するのは(特にC言語では)間違いである。

資源の確保と解放などのために、プログラム片の入口と出口が必ず対応している必要がある、といった場合などは、gotoに限らず、いわゆる「途中return」等の他の多くの技法も制限されるので、以下のgoto文の議論とはきちんと区別すべきであるし、そういった場合の制限を全てのコーディングに適用するのはただの誤りである。

構文[編集]

次のように、ラベルの付いた文と併用する。

clear:     x = 0;
……
goto clear;

goto文によって、そこからclearラベルの付いた文にジャンプし、そこから処理を続ける。

批判[編集]

Cなどの構造化プログラミング言語においては、goto文はむやみに使ってはいけないというルールが、プロジェクト等のガイドライン等として定められていることがある。これは、goto文が原始的で自由度の高すぎる機能であるため、安易なgoto文の使用はプログラムの構造化を妨げ、デバッグなどが行いにくくなり、バグの発生や、メンテナンス性・可読性の低下の原因になりやすいからである。

しかし、多重にネストしたfor文if文while文などでエラー処理や例外処理などが複雑になる場合はgoto文を使った方がプログラムがすっきりと書けるケースもあるため、プログラムの構造を熟知したプログラマが状況に応じて使い分けるものとされている。

オブジェクト指向言語の場合は、エラー処理や例外処理などの仕組みが充実しているため(オブジェクト指向とは無関係である)にgoto文が必要になるケースが少ない。そのため、言語仕様として始めから用意されていないケースもある。こうした言語としては、Javaなどが挙げられる(Javaの場合、gotoを不要とするために充実しているのは、ラベル付きbreakとcontinueであり、例外の処理はgotoよりも大きなスコープでのジャンプ(C言語ではgotoではなく、setjmp/longjmpに相当)である)。一方では、PHPで、2009年にリリースされたバージョン5.3からgotoが追加された[2]ように、高度化する言語構造の中でgoto文が一定の評価を受ける例もある。

BASICの様な言語や低レベルの制御言語ではgoto文は不可欠であり、goto文を利用しないと分岐やループを使ったプログラムが記述出来ないものもある。しかし、拡張されたBASICの中には、goto文がほとんど不必要になってしまっているものもある。

前述のように、goto文の安易な使用はプログラムの可読性を著しく低下させる。こうした可読性の低いコードのことを、制御構造が複雑に絡まっているという意味を込めて、スパゲティコードと呼ぶことがある。

goto文論争[編集]

構造化プログラミング」を提唱していたコンピュータ科学者らの一人であったダイクストラは、1968年にGo To Statement Considered Harmful(「Go To 文は有害(Harmful)とみなされる」)という刺激的な記事を国際学会ACMの学会誌Communications of the ACMに投稿し(ただし、本人が付けたタイトルはA Case Against the Goto Statementという穏便なもので、少なくともタイトルの過激さと、レターとして発表を急いだことは、編集を担当していたヴィルトによるものである)、こんにちでは構造化プログラミングに関して最も良くその名前だけが知られている論争となっている(その内実は言葉の有名さの割には全く知られていないし、そもそも内容や意味の理解は半世紀という時代の違いによって、かなり難しくなっていることも確かである)。クヌースの言葉を借りるならば、「go to 文除去の話の二番目の場面は,多くの人たちが第一幕だと思っている事実である.」[3](という解説自体も[4]1974年に書かれたものである)。

また considered harmful というフレーズはその後、定番ネタとして、しばしば似たような深刻な、あるいは軽妙な論争に関して付けられるものとなっている(英語版en:Considered harmfulの記事などを参照)。

ダイクストラの主張[編集]

“Go To Statement Considered Harmful”[5]の趣旨は次の通りである。

  • 人間が時間によって変化するプロセスを把握する能力は、プログラムの静的な関係を把握する能力に比べて劣っているため、静的なプログラムテキストの構造と時間によって変化するプロセスの構造をなるべく近づけるのが重要である。
  • そのためにはプロセスの進捗を表す簡潔な指標が必要がある。指標とは例えば実行中の行番号・その時点でのスタックトレース・行番号とループを回った回数のペアなどである。
  • 例えば、1人が部屋に入るごとにカウンタを増やしていくプログラムにおいて、カウンタが室内の人数-1である瞬間はどこにあるのかという問いに答える際に、簡潔な指標があればすぐ答えられるが、簡潔な指標がなければ正確な答えは難しくなる。
  • goto文を無条件に許してしまうと簡潔な指標は得られなくなってしまうため、高水準プログラミング言語においてはgoto文は廃止するべきである。

その一方でクヌースの指摘[6]によると、ダイクストラは“Structured Programming”[7]においてはgoto文には触れていない。実際に“Structured Programming”においては“sequencing should be controlled by alternative, condtional and repetitive clauses and procedure calls, rather than by statements transferring control to labelled points.”との1文があるのみでそれ以外では触れていない。

また、3つの基本構造についても、“Go To Statement Considered Harmful”においては“I do not claim that the clauses mentioned (引用者註: 順次・分岐・手続き呼び出し・反復) are exhaustive in the sense that they will satisfy all needs”とし、プロセスの進捗を表す簡潔な指標が存在する限りは3つの基本構造には固執していない。

「構造化プログラミングの観点からgoto文を使うのは望ましくない」ものの「単にgoto文を使わなければ見通しが良くなる」という考えは“Go To Statement Considered Harmful”[5]でも否定されており、goto文の有無のみに固執するのは不毛である。構造化プログラミングの本質の一つは、状態遷移の適切な表現方法とタイミングを見極めることである[8]

goto擁護派[編集]

一方、goto文を使わずに3つの基本構造による代替を行うと、理論上は同値であっても実際にはプログラムの実行速度や記憶容量の点で性能が劣化する場合があることを示し、goto文を擁護する意見もあった[9]

ACMの年次大会(1972)の討論会では、トップダウンでプログラムを分割するよりgoto文を使う方が適した事例があり、証明には関心がないという意見(William Wait)や、goto文を残せば選択の余地があるが、無くしてしまうと必要になったとき困るだろうという意見(Guy Steel)などが出された[10]

条件文とgoto文を正しく使うことで、FORTRANでもALGOLの基本機能を実現できることを例に挙げ、プログラマは必要な機能がプログラミング言語で直接表現できないとき、どのように実装するか工夫できるべきであるという主張もあった(S.W.スリア)[11]

また、ドナルド・クヌースは「go to 文を用いた構造的プログラミング」(『文芸的プログラミング』収録)の中で、いくつかのgotoを使ったほうが良いだろうという例を挙げているが、その中には、再帰呼出しのある正当なプログラムを、正当な変形によってループによるプログラムに書き換えた結果「ループの中に飛び込むgoto」になる、といったような例も挙げている[6][12]

gotoの現在[編集]

現在C言語を除く主流派の言語では、そのままのgoto文はほとんど見られなくなった。替わりにbreak文continue文、もしくは例外処理のような特殊脱出(去勢されたgotoとも呼ばれる(実際には関数呼出しをまたいだ、いわゆる大域脱出もできるのだから、gotoよりも例外処理のほうが強力である(が、それを理解できない者も多い)))をサポートし、単純な制御構造だけでは弱いと考えられる部分を補っている。さらにクロージャコードブロック継続のような強力な制御機構を使い、抽象度の低いgoto文を使う必要性を低くした言語もある。例えばHaskellにおいてはモナドを利用して例外や非決定性計算などの様々な制御構造を表現できる。またSmalltalkIoにおいても制御構造はブロックを扱うメソッドとして表現している。Scheme等でサポートされている継続は「引数付きgoto」と呼ばれることもある。

一方で、例えば1999年から設計されたD言語はgoto文を含んでいる[13]PHPにも2009年にリリースされた5.3において制限された形ではあるがgoto文が追加された[14]

その他の話題[編集]

それまでの職人芸的なプログラミングの時代から、構造化プログラミングというパラダイムの提唱によって、プログラミング技法の体系化を試みるプログラミング工学という学問が芽生えたと言っても過言では無いだろう[要検証 ]

なお、論文“Go To Statement Considered Harmful”は、その半ば挑戦的な題名がプログラミング以外の様々な分野に及んで評判となり、それをもじった様々な “~ Considered Harmful”といった論説やジョークが生まれたen:Considered harmful 。極めつきは、何かが有害であることだけが強調される題名の有害性を指摘した“‘Considered Harmful’ Essays Considered Harmful”であろう。

ダイクストラは What led to “Notes on Structured Programming” (『「構造化プログラミングに関する覚え書き」へと導いたもの』)で、“A case against goto statement” (『Goto 文が不利な場合』)と題した論文を投稿したが、出版を早めるために編集者により “letter to the Editor” (『編集者への手紙』)と改題され、その過程でその編集者独自の考案で新たなタイトル("The goto statement considered harmful")を付けられた。その編集者とはニクラウス・ヴィルトであった、と述べている。

同じくWhat led to "Notes on Structured Programming" においてダイクストラは、Millsによって矮小化されたgoto文廃止という概念のもと、IBMが用語としての「構造化プログラミング」を盗用したと語っている。

ダイクストラの著書は、分かりにくいことと誤解を招きやすいことで定評がある[15][16][17]。それを憂いたディビット・グリース英語版マダガスカル語版ロシア語版は、ダイクストラ流のプログラミングについて体系化した書籍「プログラミングの科学」(The Science of Programming)を書いた[16]

関連項目[編集]

参考文献・注[編集]

  1. ^ HHOS http://catb.org/~esr/jargon/html/H/ha-ha-only-serious.html
  2. ^ 新機能 - PHPマニュアル(2013年12月4日閲覧)
  3. ^ 有澤誠訳『文芸的プログラミング』 p. 45
  4. ^ (訳ではなく、原文は)
  5. ^ a b E. Dijkstra (1968). “Go To Statement Considered Harmful”. Communications of the ACM 11 (3): 147-148. CiteSeerX: 10.1.1.132.875. 
  6. ^ a b Knuth, D. E. (1974). “Structured Programming with go to Statements Computing Surveys”. ACM, New York, NY, USA 6 (4): 261-301. CiteSeerX: 10.1.1.103.6084. 
  7. ^ E. W. Dijkstra, “Structured Programming”, In Software Engineering Techniques, B. Randell and J.N. Buxton, (Eds.), NATO Scientific Affairs Division, Brussels, Belgium, 1970, pp. 84–88.
  8. ^ E.W.ダイクストラ, W.H.J.フェイエン, プログラミングの方法, 玉井浩 訳, サイエンス社, 1991.
  9. ^ Frank Rubin, "GOTO Considered Harmful" Considered Harmful, Communications of the ACM, Vol.30, Issue 3, 1987, pp.195-196.
  10. ^ B.リーヴェンワス編, ed. (1975), “GO TO 論争:第2部 GO TO 論争”, bit (共立出版) 7 (5): 10-26 
  11. ^ 金山裕 編, "構造的プログラミング −批判と支持−", bit, Vol.7, Issue 7, 1975, pp.6-13, 共立出版.
  12. ^ 「ループの中に飛び込むgoto」というのは、一般には「最も許されないタイプのgoto」と考えられているものであり、しばしば見られる、クヌースの「go to 文を用いた構造的プログラミング」を紹介して「例えば、エラー処理のように、goto文を使う方が分かりやすい場合があり、その場合、goto文を使ってもよい」といったように纏めている解説は(たとえば http://monoist.atmarkit.co.jp/mn/articles/1008/17/news092.html )その解説者が全く論旨を読めていない可能性があるので注意したい。
  13. ^ Language Reference Goto Statement
  14. ^ PHP マニュアル goto
  15. ^ 木村泉, "GO TO 論争:第3部 解説", bit, Vol.7, Issue 5, 1975, pp.27-39, 共立出版.
  16. ^ a b 二木厚吉 監修, ソフトウェアクリーンルーム手法, 日科技連, 1997.
  17. ^ 木村泉, "ダイクストラ教授とふた付き命令", bit, Vol.8, Issue 9, 1976, pp.29-34, 共立出版.

外部リンク[編集]