なぜ言語はブロックの明示的なマーカーよりもインデントを好むのですか?


11

Haskellを学んでいますが、自動インデントツールを探していました。私はあまり見ていませんでしたが、Haskellでは(Pythonのように)インデントがブロックを意味することを学びました。その結果、{}(中括弧)やbegin endキーワードなどの明示的なマーカーを使用する、Cファミリの他の言語ほど強力な自動書式設定ツールを作成することは不可能だと推測しています。

読みやすくするためにインデントを強制する言語は気にしませんが、インデントの強制と明示的なマーカーの両方の利点を理解できないため、自動化ツールはどのブロックに属するかを理解できます。

ブロックをマークするインデントの設定が、コードの見栄えを良くするためのものである場合、その利点はまだ理解できません。タブやスペースが異なるエディターや異なるフォント(モノスペースフォントは見栄えが良いなど)で異なって表されることを考えると、プログラマーがコードを適切に提示することを期待することは不可能です。現在のテキストエディタを考慮に入れることができるツールは、コードを正しくフォーマットするためにはるかに適切です。

言語設計者が明示的なブロックマーカーよりもインデントを選択するのはなぜですか?


8
答えではありませんが、Haskellはpythonよりも空白の感度をはるかにオプションにします。ほとんどの場合にセミコロンを使用し、必要に応じてブロックを中括弧で囲むことができます。let x =1; y = 2; z = 3そのままで完全に有効ですdo { putStrLn $ show x; putStrLn $ show y; putStrLn $ show z; }。それらは同じ行にある必要はありません。
-KChaloux

8
「自動書式設定ツールを作成することは不可能です」-実際には、インデント規則のためにPythonでそのような自動書式設定ツールを使用する必要はありません。
ドックブラウン

13
ええと、インデントの増加明示的なブロックマーカーです。
カールビーレフェルト

3
@ K.Gkinis:言語設計の決定の背後にある正確な動機の最適なソースは、言語設計者自身です。
ロバートハーヴェイ

3
この質問は実際には主観的ではありません。一部の言語設計者が特定の構文を選択した理由を尋ねます。これは答えられます。質問がどの構文が最適であるかを尋ねていた場合、それは主観的です。
ジャックB

回答:


13

グイド・フォン・ロッサム

books.google.com(エンファシス鉱山)で全文見ることができるGuido Van Rossumのインタビューから:

グループ化のためのインデントの選択は、Pythonの新しい概念ではありませんでした。これはABCから継承しましたが、古い言語のoccamでも発生しました。ABCの作者がoccamからアイデアを得たのか、それとも独立して発明したのか、あるいは共通の祖先がいたのかはわかりません。もちろん、私は私が他の領域(例えば、ABCは、言語のキーワードとプロシージャ名のために、私はコピーしなかったアイデアを大文字を使用)、で行ったように、ABCのリードに従わないことを選んだかもしれないが、私は機能のように来ていたかなりビット、ABCを使用している間、Cの間での無意味な議論の共通の特定の種類を廃止するように見えたとしてについては、一度にユーザーの中括弧をどこに配置しますか

Von RossumはABCから多大なインスピレーションを得ており、そのすべてをコピーする必要はありませんが、宗教戦争を避けるのに有益である可能性があるため、インデントの使用は維持されました。

また、読み取り可能なコードはグループ化を示すためにインデントを自発的に使用することもよく知っていました。インデントが中括弧を使用した構文グループ化と一致しないコードの微妙なバグに遭遇しました。したがって、バグに気づきませんでした。繰り返しますが、長いデバッグセッションは貴重な教訓を教えてくれました。

Rossumは、グループ化とインデントの不一致によるバグも目撃しましたが、コードの構造化のみにインデントを使用する方が、プログラミングエラー1から安全になります。

ドナルドE.クヌース&ピーターJ.ランディン

参照されたインタビューで、Guidoはインデントを使用するというDon Knuthのアイデアに言及しています。これは、再発見さたKnuth Indentation Quoteで詳しく説明されています。これは、構造化プログラミングとgotoステートメントを引用しています。Knuthは、Peter John LandinのThe next 700 programming languages(インデントについてのディスカッションセクションを参照)も参照しています。Landin は、開始/終了ブロックではなくインデントを使用した最初の言語のように見えるISWIMを設計しました。これらの論文は、プログラムを構造化するためにインデントを使用することの実現可能性に関するものであり、実際にそうすることを支持する議論ではありません。


1.これは実際には、発生するはずのプログラミングエラーをキャッチして回復するために、グループ化構造と自動フォーマットの両方を使用することを支持する議論だと思います。Pythonでインデントを台無しにした場合、コードをデバッグする人はどちらが正しいかを推測する必要があります。

if (test(x)):
  foo(x)
  bar(x)

シャルbar常に呼び出されるかだけテストが成功した場合はどうなりますか?

グループ化構造は、コードの自動インデント時に間違いを見つけるのに役立つ冗長性のレベルを追加します。Cでは、同等のコードを次のように自動インデントできます。

if (test(x))
  foo(x);
bar(x);

barと同じレベルにすること を意図している場合foo、コード構造に基づいた自動インデントにより、fooとの周りに中括弧を追加することで修正できる問題があることがわかりますbar

Pythonの:インデントについての神話、Cからおそらく悪い例があります:

/*  Warning:  bogus C code!  */

if (some condition)
        if (another condition)
                do_something(fancy);
else
        this_sucks(badluck);

これは上記と同じです。Emacsでは、ブロック/関数全体を強調表示し、Tabキーを押すと、すべてのコードが再インデントされます。人間のインデントとコード構造の不一致は、何かがずれていることを示しています(それと前のコメント!)。

その上、Cでインデントがオフになっている中間コードは、単にmasterブランチを通過しません。すべてのスタイルチェックが行われると、GCC / Jenkinsが悲鳴を上げます。私は最近、Pythonで上記で説明したものと同様の問題を抱えていました。Cで閉じ括弧を超えるコードがある場合もありますが、Tabキーを押すとコードが「間違って」インデントします。これはバグを確認するもう1つの機会です。


3
「宗教的な戦争を避けるために...」私は、本当の理由がささいなものであることに驚いています。
ロバートハーヴェイ

1
@RobertHarvey:そのフレーズの強調は、ヴァンロッサムではなく、コアダンプによるものです。文脈でvan Rossumの引用を読んだ場合、それが主な理由ではありません。
ジャックB

@JacquesB回答を編集できるように、引用から欠落しているコンテキストを教えてください。
コアダンプ

4
個人的なコメントはありませんが、Pythonのインデントを台無しにすると、バグが発生します。Cの中括弧を台無しにすると、バグが発生します。自動インデントを使用する場合、両方の言語でまったく同じです。そして、自動インデントを使用しない場合、バグはPythonでは不可能な方法でCに隠されてしまいます。
ジャックB

2
@JacquesBは、閉じ括弧を入力することが積極的に行われるためです。インデントを十分に行わないと、忘れることがあります。もちろん、適切なタイミングでブレースを閉じることを忘れることができますが、最終的にはそれを実行し、それについて考える別の機会を得る必要があります。pythonはインデントに注意を払うので、初心者にはpythonが適していると思います。
-marstato

7

これは非常に主観的であり、多くの火炎戦争の原因です。しかしながら:

ブロックインデントを区切る記号がある、同じ情報を2つの異なる方法で表現するため、DRY原則違反します。自動インデントツールの存在は、このDRY違反の症状です。インデントを自動的に生成できることは、それが冗長な情報であることを示し、インデントとシンボル同期しなくなり、誤解を招くコードにつながる可能性があることを意味します。

Python Design and History FAQはこれを非常に明確に述べています:

Pythonがステートメントのグループ化にインデントを使用するのはなぜですか?

Guido van Rossumは、グループ化にインデントを使用することは非常にエレガントであり、平均的なPythonプログラムの明快さに大きく寄与すると考えています。ほとんどの人はしばらくしてこの機能を愛するようになります。

開始/終了ブラケットがないため、パーサーと人間のリーダーが認識するグループ化の間に不一致はありません。

Python用の自動インデントツールを作成できないのは事実ですが、これは良いことです。つまり、調整に自動化ツールが必要な構文に冗長性がないことを意味します。

タブとスペースはPythonの正当な懸念事項であり、同じコードベースでタブとスペース(インデント用)を混在させないことをお勧めします。

Pythonは、(現在は廃止された)先行言語ABCから重要なインデントを継承しました。ABCは、ユーザビリティテストを使用して設計を指示した数少ないプログラミング言語の1つです。したがって、構文に関する議論は通常主観的な意見と個人的な好みに帰着しますが、重要なインデントの選択は実際にはより健全な基盤を持っています。


6
ダブルエントリー会計もDRYに違反します。冗長性が機能である場合があります。
コアダンプ

3
@coredump:本当ですが、意図的に設計された冗長性です。Pythonを含むほとんどのプログラミング言語には、意図的に選択された冗長性が含まれています。たとえば、pass自動的に推論される可能性のあるキーワードですが、明示的であることを要求することで間違いを発見できます。開始/終了シンボル(コンパイラー)とインデント(人間の読者)の両方の偶発的な冗長性は、キャッチするよりも多くの間違いを引き起こすようです。少なくとも、これはヴァンロッサムの見解のようです。
ジャックB

@coredump-なぜ私が会計士ではないのかがわかりました。
-JeffO

3
@coredump COBOL PROCEDURE DIVISION.も見逃していますか?DATA DIVISIONこれらの新しい言語のどこで終わりと手続きが始まるかはわかりません。
msw

2
@coredump:「インデントを見ることは、私が念頭に置いていたものと矛盾するので、エラーを防ぐのに十分です」-正確に。
ジャックB

2

言語設計者は、セミコロンとブレースがコードの読み取り時にノイズを追加し、生産性を損なうと信じている(または少なくとも潜在的なユーザーが信じていると思う)ため、構文的に重要な空白を選択します。別の一般的な理由は、悪い/一貫性のないコーディングスタイルが読みやすさを損なうことです。共通のインデントスキームを強制することにより、言語の全体的な読みやすさが向上します。IDEの自動フォーマットがより一般的である今では、その後者の理由はそれほど重要ではありませんが、まだ適用できます。


1
セミコロンと中括弧のノイズを考慮する理由がわかります。しかし、4/8/12倍のスペースを入力しなければならないのは生産的ではありませんか?そして、もしあなたが(それらが目に見えないので)見逃しているなら、あなたは問題を抱えています。
モニカの復元

5
そのため、スペースの代わりにタブを使用するか、タブを4スペースブロックに変換する方法を理解するIDEを使用します。
ロバートハーベイ

@ K.Gkinis:インデントは非表示ではありません。行末の空白のみが見えませんが、これはどの言語でも重要ではありません。タブとスペースを混在させる場合にのみ、問題が発生します。だからそれをしないでください。
ジャックB

@JacquesB:インデントの可視性/非可視性の問題は、人間がスペースとタブの違いを認識できないことが多いのに対し、コンピューターはできることであることが多いことです。そのため、インデントは表示されますが、コンピューターがインデントを解釈する方法は異なる場合があります。それが本当の問題です。コンピュータが目に見えない文字を人間とは異なる方法で扱うとき。人間は画面上のインデントを距離として測定し、コンピューターは文字の文字数として測定する場合があります。 それは見えない部分です。
ブライアンオークリー

@BryanOakley:ええ、これがインデントでタブとスペースを混ぜてはいけない理由です。
ジャックB
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.