なぜ最近のプログラミング言語で変数名の後に型が続くのですか?


57

ほぼすべての最新のプログラミング言語(Go、Rust、Kotlin、Swift、Scala、Nim、Pythonの最終バージョンでも)で、型が常に変数宣言の変数名の後に来るのはなぜですか?

なぜx: int = 42ありませんかint x = 42
後者は前者よりも読みにくいですか?
それは単なるトレンドですか、このソリューションの背後には本当に意味のある理由がありますか?



3
うん、大丈夫だよ。これは特にKotlin言語を指しますが、質問(およびその回答)は、この慣行を持つすべての言語に適用されます。
ロバートハーヴェイ


2
申し訳ありませんが、グーグル検索でKotlinに関する質問を見ましたが、「Kotlin(Go、Rust、...)開発チームはこのように決定したので」などの回答が得られないように再質問しました。もっと一般的な答えに興味がありました。なぜそれが一種の流行になったのですか?
アンドレポリカニン

2
Hihi、つまり(Object)PascalであるDelphiは、その創始以来変数名の後に型があり、前世紀の暗い時代に遡ると、近代的です;)ところで、読みやすさはあなたが何であるかに大きく影響されます慣れている。Delphiから来て、C#のvar名の前にその型があり、かなり長い間頭を打ちました。
マルジャンヴェネマ

回答:


64

言及したすべての言語は型推論をサポートしています。つまり、型は、簡単に判別できる型を持つ初期化式を提供するときに十分にスマートであるため、それらの言語の宣言のオプション部分です。

式のオプション部分をさらに右に配置すると、解析のあいまいさが減り、その部分を使用する式と使用しない式の一貫性が向上するため、これは重要です。varオプションのものに到達する前に、キーワードと変数名の両方が必須であることがわかっている場合、宣言を解析する方が簡単です。理論的には、コンピューターでの解析を容易にするこれらのすべてが人間の全体的な可読性を向上させるはずですが、それはもっと議論の余地があります。

次のようなC ++のような「非近代的な」言語が持っているすべてのオプションのタイプ修飾子、考えるとき、この引数は特に強い取得*ポインタのため、&、参照のためにconstvolatileというように。複数の宣言にカンマを挿入int* a, b;するとb、ポインターを作成しないなどの非常に奇妙なあいまいさが発生し始めます。

でもC ++は今の形で宣言「右のタイプ」をサポートauto x = int{ 4 };し、それはいくつかの利点を持っています


2
var解析の簡素化の大部分を提供する、そのような必須キーワードの存在を認めたための+1 。
8bittree

2
varキーワードの存在は、名前優先表記法の目的に反しませんか?var userInput: String = getUserInput()上書きの利点はありませんString userInput = getUserInput()。利点userInput = getUserInput()は、も許可されている場合にのみ関連しますが、それはスコープ変数の暗黙的な宣言を意味します。
kdb

2
C#やC ++などの言語の@kdbは、var userInput = getUserInput()またはauto userInput = getUserInput()であるため、コンパイラgetUserInput()は戻り値を知っているStringため、型推論キーワードで指定する必要はありません。userInput = getUserInput()もちろん、宣言する前に使用します。
ウェストールマン

32

ほぼすべての最新のプログラミング言語(Go、Rust、Kotlin、Swift、Scala、Nim、Pythonの最終バージョンでも)で、型が常に変数宣言の前にではなく後に来るのはなぜですか?

あなたの前提には2つの面で欠陥があります:

  • 識別子のに型を持つ新しいようなプログラミング言語があります。C♯、D、またはセイロンなど。
  • 識別子の後の型を持つことは新しい現象ではなく、少なくともPascal(1968〜1969年に設計され、1970年にリリースされた)にまで遡りますが、実際には〜1902から始まる数学型理論で使用されました。ML(1973)、CLU(1974)、Hope(1970s)、Modula-2(1977–1985)、Ada(1980)、Miranda(1985)、Caml(1985)、Eiffel(1985)、Oberonでも使用されました。 (1986)、Modula-3(1986–1988)、およびHaskell(1989)。

Pascal、ML、CLU、Modula-2、およびMirandaはすべて非常に影響力のある言語であったため、このスタイルの型宣言が普及したままであることは驚くことではありません。

なぜx: int = 42ありませんかint x = 42?後者は前者よりも読みにくいですか?

可読性は親しみの問題です。個人的には、中国語は読めないと思っていますが、中国人は読めないようです。学校でパスカルを学び、エッフェル、F♯、ハスケル、スカラに手を出して、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での関数ポインター型についても話さないでください。)

前述の言語のいくつかの設計者は、この主題に重点を置いています。

  • Go FAQGoの宣言構文も参照):

    宣言が逆向きなのはなぜですか?

    Cに慣れている場合にのみ逆になります。Cでは、変数は型を表す式のように宣言されるという概念があります。結果は混乱する可能性があります。関数ポインタを検討してください。Goは式と型の構文をほとんど分離し、それによって物事を簡素化します(*ポインターにプレフィックスを使用することは、ルールを証明する例外です)。Cでは、宣言

    int* a, b;
    

    aポインタであることを宣言しますが、ポインタではありませんb。囲inで

    var a, b *int
    

    両方がポインターであることを宣言します。これはより明確で定期的です。また、:=短い申告書は、完全な変数宣言は、同じ順序を提示しなければならないと主張している:=ので

    var a uint64 = 1
    

    と同じ効果があります

    a := uint64(1)
    

    また、構文は、式の文法だけではなく、型の明確な文法を持つことで簡素化されます。などのキーワードはfuncchan物事を明確にします。

  • Kotlin FAQ

    なぜ型宣言が右側にあるのですか?

    コードが読みやすくなると信じています。また、いくつかの便利な構文機能を有効にします。たとえば、型注釈は簡単に除外できます。Scalaもこれが問題ではないことを証明しています。

  • Scalaでのプログラミング

    Javaとの大きな違いは、型注釈の構文に関係します。これは、Java の「variable: Type」ではなく「Type variable」です。Scalaの接尾辞タイプの構文は、Pascal、Modula-2、またはEiffelに似ています。この逸脱の主な理由は、型推論に関係しています。これにより、変数の型やメソッドの戻り型を省略できることがよくあります。" 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 { ... }

そして、私たちは、他の人が他の方法で考えることができる方法を単に理解していません!

個人的には、彼らの「主張」は他の人よりも説得力が低いと感じています。


4
タイプを除外して、まだ簡単な解析を持っている能力をを添加することによって付与されているようだvarautolet型宣言がオンになっていない変数のどちら側によって、等。var Int x = 5または、Int var x = 5両方をに短縮することもできvar x = 5ます。
8bittree

5
慣れて、オプションのtype引数が強力になれば読みやすくなりますが、IDEは型に基づいて変数名を自動的に提案できないことを指摘したいと思います。TypeScriptを書くときにそれが恋しいです。
ピエールヘンリー

"Your premise is flawed on two fronts" これらのすべては、C#またはD.より新しい
デット

3
「しかし、これは実際にはあまり意味がありません。基本的には、型を書かないと言う型を明示的に書かなければなりません。」まあ、あなたの例では、右入力タイプはまったく同じです...また、それが意味をなさないことにも同意しません。funcGoとまったく同じ意味です。
ソペル

4

ちなみに、Pascalもそれを行っており、新しい言語ではありません。しかし、それは最初から設計されたアカデミックな言語でした。

変数名から始める方が意味的に明確だと思います。タイプは技術的な詳細にすぎません。クラスを現実のモデルのように読みたい場合は、エンティティの名前を最初に、技術的な実装を最後に置くのが理にかなっています。

C#とjavaはCに由来するため、経験のあるプログラマを混乱させないために、「先行技術」を尊重する必要がありました。


3
Adaもそのようにしますが、Adaは「アカデミック言語」ではないことは間違いありません。
ジョンR.ストローム

それはパスカルとのModula 2から重くcribbedので、エイダはそれをやった
ゴートロボット

2
@StevenBurnap、クイック検索により、WirthのModula-2に関する最初の本が1982年半ばに出版されたことが明らかになりました。Adaはその数年前に開発中で(DoD1は1977年かそこらで、私が覚えているように)、1983年にANSI標準とMIL-STDの両方として標準化しました。Adaの候補を提出した4つのチームはすべてPASCALを取得しました出発点として。(Bell Labsは、Cに基づいて候補言語を提出するようDoDから招待されました。Cは当時ではなく、DoDミッションクリティカルなソフトウェアにとって十分な堅牢性はないと言って、彼らは否定しました。)
John R. Strohm

誤解しているに違いない。ワースはエイダに関係していたと思いました。
ロボット

Pascalはアカデミックな言語から始まりましたが、90年代の終わりまでに、Delphiを介してWindowsアプリを書く言語になりつつありました。賞品を盗んでください。ただし、レガシーWindowsアプリの世界では、まだ大量のDelphiが見られます。
シェイン

1

なぜx: int = 42ありませんかint x = 42?後者は前者よりも読みにくいですか?

このような単純な例では、大きな違いはありませんが、もう少し複雑にしましょう。 int* a, b;

これは、Cでの実際の有効な宣言ですが、直感的には見た目どおりに動作しません。typeの2つの変数を宣言しているように見えますint*が、実際には1つと1つint*を宣言していますint

言語の宣言で変数名のに型を置くと、その問題に遭遇することは不可能です。


4
後に型宣言を移動するとこれに影響する理由はわかりません。あるx, y *int;2 *intまたは1 *intと1 int?作成int*または*int代わりに、二つのうちの一つのトークンは、それを解決するだろう、などの追加の構文要素使用して:どちらの方向に働くことができ、。
8bittree

@ 8bittree私がよく知っている名前優先宣言を使用するすべての言語は、名前と型の間に、:またはなどの追加のトークンを使用しますas
メイソンウィーラー


2
そしてGoでは、x, y *int「int-to-int型の2つの変数xとyを宣言する」ことを意味します。
Vatine

10
C#はプレフィックス構文を使用しますが、int[] x, y2つの配列として扱います。問題の原因となるのは、変数の単項演算子(およびプレフィックスとポストフィックスの組み合わせ)としてこれらの修飾子を扱うのは、愚かなC構文だけです。
CodesInChaos
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.