なぜほとんどすべての最近のプログラミング言語(Go、Rust、Kotlin、Swift、Scala、Nim、さらにPython最後のバージョン))の型は、変数宣言の変数名の後に来るのですか?前じゃない?
なぜ x: int = 42
ではなくint x = 42
?
後者は前者より読みやすいですか?
それは単なる傾向ですか、それともこのソリューションの背後に本当に意味のある理由がありますか?
あなたが言及したすべての言語はtype inferenceをサポートします。つまり、型は宣言のオプションの部分ですこれらの言語では、簡単に決定できる型を持つ初期化式を提供するときに、それらを入力するのに十分スマートです。
式のオプション部分をさらに右に配置すると、解析のあいまいさが減少し、その部分を使用する式と使用しない式の間の一貫性が高まるため、これは重要です。オプションのものに到達する前に、var
キーワードと変数名の両方が必須であることがわかっている場合は、宣言を解析する方が簡単です。理論的には、コンピュータでの解析を容易にするこれらすべてのものも人間の全体的な可読性を改善する必要がありますが、それははるかに議論の余地があります。
この引数は、C [++]のような「非モダン」言語が持つすべてのオプションの型修飾子(ポインタの場合は*
、参照の場合は&
、const
、 volatile
など。複数の宣言にカンマを入れると、int* a, b;
がb
をポインターにしないなど、非常に奇妙な曖昧さが生じ始めます。
C++でも、auto x = int{ 4 };
の形式で「右側の型」宣言をサポートするようになりました いくつかの利点があります 。
なぜほとんどすべての現代のプログラミング言語(Go、Rust、Kotlin、Swift、Scala、Nim、さらにPython最後のバージョン))の型は常に変数宣言の前ではなく、変数宣言の後に来るのですか?
あなたの前提は2つの面で欠陥があります:
Pascal、ML、CLU、Modula-2、およびMirandaはすべて非常に影響力のある言語だったので、このタイプの型宣言が人気を保っていることは驚くに値しません。
なぜ
x: int = 42
ではなくint x = 42
なのですか?後者は前者より読みやすいですか?
読みやすさは親しみやすさの問題です。個人的には中国語は読めないと思いますが、どうやら中国人は読めません。学校でパスカルを学び、エッフェル、F♯、Haskell、Scalaに手を出して、TypeScript、Fortress、Go、Rust、Kotlin、Idris、Frege、Agda、ML、Ocamlなどを見てきたので、私にはまったく自然に見えました。 。
それは単なる傾向ですか、それともそのようなソリューションの背後に本当に意味のある理由がありますか?
それがトレンドだとすれば、それはかなり持続的です。私が述べたように、それは数学の100年前にさかのぼります。
識別子の後に型があることの主な利点の1つは、推論したい場合に型を省略しやすいことです。宣言が次のようになっている場合:
val i: Int = 10
次に、型を省略して次のように推論させるのは簡単です。
val i = 10
一方、型が次のように識別子の前にある場合:
Int i = 10
次に、パーサーが式と宣言を区別するのが難しくなります。
i = 10
言語デザイナーが通常思いつくソリューションは、タイプの代わりに書かなければならない「タイプを書きたくない」キーワードを導入することです:
var i = 10; // C♯
auto i = 10; // C++
しかし、これは実際にはあまり意味がありません。基本的に、型を記述しないことを示す型を明示的に記述する必要があります。えっ?省略した方がはるかに簡単で賢明ですが、文法がはるかに複雑になります。
(そしてCの---(関数ポインタ型 については話さないでください。)
前述の言語のいくつかの設計者は、この問題について検討しました。
なぜ宣言が逆になっているのですか?
Cに慣れている場合にのみ、これらは逆になります。Cでは、変数はその型を表す式のように宣言されるという概念です。これはいいアイデアですが、型と式の文法はうまく混ざりません。結果は紛らわしいかもしれません。関数ポインタを検討してください。 Goは主に式と型の構文を分離し、それによって物事を簡素化します(ポインターに接頭辞
*
を使用することは、ルールを証明する例外です)。 Cでは、宣言int* a, b;
a
をポインタとして宣言しますが、b
は宣言しません。囲碁でvar a, b *int
両方をポインタとして宣言します。これはより明確でより規則的です。また、
:=
短い宣言フォームは、完全な変数宣言は:=
と同じ順序を示す必要があると主張しています。var a uint64 = 1
と同じ効果があります
a := uint64(1)
構文解析は、式の文法だけでなく、型ごとに異なる文法を使用することによっても簡素化されます。
func
やchan
などのキーワードを使用すると、わかりやすくなります。
右側に型宣言があるのはなぜですか?
これにより、コードが読みやすくなります。さらに、いくつかのニース構文機能を有効にします。たとえば、型注釈を省略するのは簡単です。 Scalaも問題ないことを証明しています。
Javaからの主な逸脱は、型注釈の構文に関係します。Javaでは "
variable: Type
"ではなく "Type variable
"です。Scalaの接尾辞型構文はPascal、Modula-に似ています2、またはエッフェル。この偏差の主な理由は、型推論に関係しているため、変数の型またはメソッドの戻り型を省略できることがよくあります。「variable: Type
」構文を使用すると、簡単です—コロンとタイプを省くだけです。しかし、Cスタイルの "Type variable
"構文では、タイプを省略することはできません。定義を開始するためのマーカーはもうありません。欠落している型のプレースホルダー(C♯3.0、これは型の推論を行いますが、この目的のためにvar
を使用します)このような代替キーワードは、Scalaのアプローチよりもその場しのぎで規則性が低く感じられます。
注: Ceylonの設計者は、プレフィックス型構文を使用する理由も文書化しています :
接尾辞型注釈の代わりに接頭辞
PascalとMLを宣言名の後に置くのではなく、CとJavaを最初に型アノテーションを置く際に使用するのはなぜですか?
私たちはこれを考えているので:
shared Float e = .... shared Float log(Float b, Float x) { ... }
これよりもはるかに読みやすいです:
shared value e: Float = .... shared function log(b: Float, x: Float): Float { ... }
そして、私たちは単に誰かが他の方法で考えることができる方法を単に理解していません!
個人的に、私は彼らの「議論」が他の人よりも説得力がないと感じています。
パスカルもちなみにそれを行い、新しい言語ではありません。それは一から設計された学術言語でした。
変数名から始める方が意味的に明確だと思います。タイプは単なる技術的な詳細です。現実のモデルのようなクラスを読みたい場合は、エンティティの名前を最初に置き、技術的な実装を最後に置くのが理にかなっています。
C#とJavaはCに由来するため、経験豊富なプログラマーを混乱させないように、「先行技術」を尊重する必要がありました。
なぜ
x: int = 42
ではなくint x = 42
なのですか?後者は前者より読みやすいですか?
そのような単純な例では、それほど大きな違いはありませんが、もう少し複雑にしてみましょう:int* a, b;
これは、Cでの実際の有効な宣言ですが、本来あるべきように直感的には機能しません。 int*
型の2つの変数を宣言しているようですが、実際にはint*
とint
の1つを宣言しています。
あなたの言語がその宣言に型after変数名を置く場合、その問題は実行することが不可能です。