1

私はCを学んでいて、Mathematicaでプログラミングする方法をちょっと知っています。

Mathematicaでは、次のように書くだけで変数を宣言できます。

a=9
a="b"
a=9.5

そしてMathematicaは、ある種のパターンを読んで見つけるだけで、これがどのような変数であるかを自然に理解しているようです。(Int、char、float)。Pythonにも同じ機能があると思います。

Cにいる間、私はそれが最初に何であるかを言わなければなりません:

int num;
char ch;
float f;

num=9;
ch='b';
f=9.5;

これは他の言語にも及ぶことを私は知っています。だから私の質問は:なぜプログラミング言語はこの種の変数宣言を必要とするのでしょうか?

このトピックに関するリファレンスは非常に役立ちます。

4

6 に答える 6

6

Mathematica、Python、およびその他の「動的に型付けされた」言語には、値と型で構成される変数がありますが、C などの「静的に型付けされた」言語には、値だけで構成される変数があります。これは、変数を格納するために必要なメモリが少なくて済むことを意味するだけでなく、動的に型付けされた言語では、実行時に変数の型を設定して調べて、変数に含まれる値の型を知る必要があります。その上で実行できる/実行する必要があり、コンパイル時に認識されます。その結果、静的に型付けされた言語はかなり高速になります。

さらに、最新の静的に型付けされた言語 (C# や C++11 など) には型推論があるため、多くの場合、型について言及する必要はありません。Haskell のような型推論を備えた非常に高度な静的型付け言語では、型を指定しなくても大規模なプログラムを記述できるため、動的型付け言語の簡潔さと利便性を備えた静的型付け言語の効率が得られます。

于 2012-08-30T04:59:37.800 に答える
3

他のほとんどの回答が示唆しているように見えるものとは対照的に、これはタイプとはほとんど関係がなく、簡単に推測できます(効率は言うまでもありません)。それはすべて、スコープの明確なセマンティクスに関するものです。

言語構造の複雑なネストを許可する言語では、変数がどこに属しているか、およびどの識別子が同じ変数を参照しているかについて明確な規則を持つことが重要です。そのために、すべての変数には、それが見える場所を定義する明確なスコープが必要です。一般的なケースでは不可能な、変数の明示的な宣言なし (型注釈の有無にかかわらず)。

単純な関数を考えてみましょう (ネストされたスコープの他の形式で同様の例を作成できます)。

function f() {
  i = 0
  while (i < 10) {
    doSomething()
    i = i + 1
  }
}

function g() {
  i = 0
  while (i < 20) {
    f()
    i = i + 1
  }
}

何が起こるのですか?伝えるには、どこにバインドされるかを知る必要がありますi:グローバルスコープまたはローカル関数スコープ? 後者は、両方の関数の変数が完全に分離されていることを意味しますが、前者はそれらを共有し、この特定の例は永久にループします (ただし、グローバル スコープは他の例で意図されているものである可能性があります)。

上記と対比してください

function f() {
  var i = 0
  while (i < 10) {
    doSomething()
    i = i + 1
  }
}

function g() {
  var i = 0
  while (i < 20) {
    f()
    i = i + 1
  }
}

var i

function f() {
  i = 0
  while (i < 10) {
    doSomething()
    i = i + 1
  }
}

function g() {
  i = 0
  while (i < 20) {
    f()
    i = i + 1
  }
}

これにより、考えられるさまざまな意味が完全に明確になります。

一般に、(1) プログラマーが実際に意図したことを推測でき、(2) プログラムの拡張またはリファクタリングの下で​​十分に安定している、適切なルールはありません。プログラムが大きく複雑になるほど、厄介になります。

毛むくじゃらのあいまいさと驚くべきエラーを回避する唯一の方法は、変数の明示的な宣言を要求することです。これは、すべての合理的な言語が行うことです。(これは言語設計の 101 であり、50 年間続いていますが、残念ながら、新しい世代の言語「設計者」が、特にいわゆるスクリプト言語で、同じ古い過ちを何度も繰り返すことを妨げていません。難しい方法でレッスンを行い、間違いを修正します。たとえば、ES6 の JavaScript など)。

于 2012-09-01T14:25:04.500 に答える
3

C を効率的なバイナリにコンパイルするには、宣言が必要です。基本的に、これが C が Mathematica よりもずっと速い理由の大きな部分を占めています。

于 2012-08-30T04:47:13.293 に答える
2

これは型とは関係ありません。型のない変数宣言を持つ JavaScript を考えてみましょう。

var x = 8; y = 8;

その理由は、JavaScript は、古い名前を参照しているのか、新しい名前を作成しているのかを知る必要があるためです。上記のコードは、既存の s をそのまま残しますが、周囲のスコープにxある既存の s の古い内容を破壊します。y

より広範な例については、この回答を参照してください。

于 2012-08-31T01:01:29.387 に答える
2

コンパイラが正しい値の型が変数に割り当てられていることを確認できるようにするには、変数の型が必要です。根底にあるニーズは言語によって異なります。

于 2012-08-30T05:00:28.687 に答える
1

基本的に、高レベルの仮想マシンまたはインタープリター (python、Mathematica ...) によって解釈されている言語と、実行されているネイティブ バイナリ (C、C++ ...) にコンパイルされている言語の 2 種類の言語を比較しています。物理マシン、明らかに独自の仮想マシンを定義できれば、非常に限られた数の構造と基本的な命令セットなどを備えた非常に制限された物理マシンに対して、言語がどれほど動的で強力かについて驚くべき柔軟性が得られます.. ..

仮想マシンにコンパイルされたり解釈されたりする一部の言語では型を宣言する必要がありますが (Java、C#)、これは単純にパフォーマンスのために行われます。実行時に型を推測する必要があるか、基本型を使用する必要があることを想像してください考えられるすべての型を使用すると、かなりの量のリソースが消費されることは言うまでもありません。言うまでもなく、一部のものをネイティブに実行する JIT (ジャスト イン タイム コンパイラ) の実装が非常に困難になります。

于 2012-08-30T04:58:59.050 に答える