段階的な入力:「静的型システムを持つほとんどすべての言語には動的型システムもあります」


20

Aleks Bromfieldによるこの主張は次のように述べています。

静的型システムを持つほとんどすべての言語には、動的型システムもあります。C以外に、私は例外を考えることはできません

これは有効な主張ですか?実行時のReflectionクラスまたはLoadingクラスを使用すると、Javaがこのようになりますが、この「漸進型付け」の考え方を多数の言語に拡張できますか?


私は言語の専門家ではありませんが、動的型があるとは思わないことをすぐに思い浮かびます(ネイティブでは、これらを一緒に詰めることはできないと言っていません)
-Fortran

4
私は言語の専門家であり、この男が何を主張しているかはわかりません。「静的」および「動的」は誤った呼び名であり、通常は型チェック/分析の時間を示します(コンパイル時または実行時)。一部の言語は両方を調整します(たとえば、コンパイル中にサポートされていない型の操作を禁止し、ランタイム中にClassCastExceptionなどの例外を発生させることにより)。その場合、Cは通常、実行時に型チェックを実行しません。ラングと言います。「動的型システム」がないのは意味がありません。
チアゴ・シウバ

回答:


37

オリジナルのトゥイーターはこちら。:)

まず第一に、私のツイートが真剣に受け止められているのを少し面白がって/ショックを受けました!これが広く普及することになると知っていたら、30秒以上かけてそれを書いていたでしょう!

Thiago Silvaは、型システムではなく、「静的」および「動的」が型チェックをより正確に記述することを指摘するのが正しいです。実際、言語が静的または動的に型付けされていると言っても、実際には正確ではありません。むしろ、言語には型システムがあり、その言語の実装は、静的チェック、動的チェック、またはその両方、またはどちらも使用せずに型システムを強制する場合があります(ただし、非常に魅力的な言語実装ではありません!)。

たまたま、特定のタイプシステム(またはタイプシステムの機能)が静的チェックを受け入れやすくなり、特定のタイプシステム(またはタイプシステムの機能)が動的チェックを受け入れやすくなります。たとえば、特定の値が常に整数の配列でなければならないことをプログラムのテキストで指定できる言語の場合、静的チェッカーを記述してそのプロパティを検証するのは合理的です。逆に、言語にサブタイプがあり、ダウンキャストが許可されている場合、実行時にダウンキャストの有効性をチェックするのはかなり簡単ですが、コンパイル時に行うのは非常に困難です。

ツイートで私が本当に意味したのは、大部分の言語実装が動的な型チェックをある程度実行するということです。または、同様に、大多数の言語には静的にチェックするのが難しい(不可能ではないにしても)いくつかの機能があります。ダウンキャスティングはその一例です。他の例には、算術オーバーフロー、配列境界チェック、およびヌルチェックが含まれます。これらのいくつかは状況によっては静的にチェックできますが、概して、実行時にチェックを行わない言語実装を見つけるのは困難です。

これは悪いことではありません。これは、私たちの言語に適用する多くの興味深いプロパティがあり、静的にチェックする方法が実際にはわからないという観察にすぎません。また、「静的型」と「動的型」のような区別は、一部の人々があなたに信じさせるほど明確ではないことを思い出させてください。:)

最後の注意点:「強い」および「弱い」という用語は、プログラミング言語の研究コミュニティでは実際に使用されておらず、実際には一貫した意味を持ちません。一般に、ある言語には「強いタイピング」があり、他の言語には「弱いタイピング」があると言うとき、彼らは自分の好きな言語(「強いタイピング」を持つ言語)がそれらを妨げると本当に言っていることがわかりました他の言語(「タイピングが弱い」言語)ではできない、または逆に、自分の好きな言語(「タイピングが弱い」言語)が他の言語( 「強いタイピング」のあるもの)はそうではありません。


9
「私たちの言語に適用したい興味深いプロパティがたくさんあり、静的にチェックする方法が実際にはわからないという観察にすぎません。」–さて、それを行う方法がわからないだけではありません。私達はちょうどチェックする方法がわからないではないという興味深い特性である「この入力のため、このプログラム停止がない」が、実際に我々はやるノウハウが不可能チェックします。
ヨルグWミットタグ

「他の例には、算術オーバーフロー、配列境界チェック、およびヌルチェックが含まれます。」型システムにはこれらのプロパティをチェックする言語がいくつかありますが、ほとんどの動的型付け言語でも、これらは通常型ではなく値の機能です。(ただし、「Null」チェックは静的型システムの一般的な機能です。)
porglezomp

そこダイナミックなタイプのシステム、および静的な型システムが。どちらも強制されていない場合でも、それらはまだ存在し、何が正しいか、何がエラーであるかを説明します。言語/実装は、どちらかをチェックする場合としない場合があります。ところで、静的型システムと動的型システムは一貫している必要がありますが、定義によりそうではありません。
エラザー

すべての言語には、特定の操作の実行を禁止する一連のルールである動的型システムがあります。
エラザー

7

はい、そうです。静的に型付けされた任意の言語でプロパティバッグを使用できます。構文はひどいものになりますが、同時に動的に型指定されたシステムのすべての不利な点があります。そのため、コンパイラでC#のような優れた構文を使用できる場合を除き、実際には利点はありませんdynamic

また、Cでも簡単にできます。

他の答えに対する反応:人々は静的/動的型付けを強い/弱い型付けと間違えていると思います。動的型付けとは、実行時にデータの構造を変更できることと、コードが必要とするものにちょうど適合するデータをコードが使用できることです。これはDuck Typingと呼ばれます。

リフレクションに言及しても、全体を語ることはできません。なぜなら、リフレクションでは既存のデータ構造を変更できないからです。C、C ++、Java、C#のいずれかのクラスまたは構造に新しいフィールドを追加することはできません。動的言語では、既存のクラスに新しいフィールドまたは属性を追加することは可能ですが、実際には非常に一般的です。

例えば、PythonからCへのコンパイラーであるCythonを見てください。静的なCコードを作成しますが、型システムは動的な性質を保持します。Cは静的に型付けされた言語ですが、Pythonからの動的な型付けをサポートできます。


技術的には、バージョン4以降のC#でそれを行うことができますがExpandoObject、JavaScriptやRubyとは異なり、非常にオプトインプロセスです。それでも、あなたは非常に重要な点を指摘しました。つまり、アヒルのタイピング(開発者の99%が「動的にタイピングされた」と実際に言うもの)とリフレクションはまったく同じものではありません。
アーロンノート

また、Pythonには実際のアヒルの型付け機能がないことも追加できます。「自分で実装する」ためのフックがいくつかあります(True「このクレイジーなオブジェクトは定義しているクラスのインスタンスです」と言うために戻ることができる魔法のメソッドがあります)。OCamlには、私が理解している限り、この機能がありますが、実際にはわかりません。
vlad-ardelean 14

6

動的言語は静的言語です。一般に「動的型付け」と呼ばれるものは、実際には静的型付けの特別な場合です。つまり、1つの型のみに制限している場合です。思考実験として、のみ使用してJavaやC#でプログラムを書いて想像Object変数/フィールド/パラメータと呼び出す前に、すぐにダウンキャストの任意の方法を。PythonやJavascriptなどの言語を「ユニタイプ」と呼ぶ方が正確です。(この主張は、そのようなJavaまたはC#プログラムが多くのサブタイプを使用することを考えると、多くの人々を混乱させる/仲間にするでしょう。

Cでも「動的な」タイピングを使用できることに注意してください-任意のポインターをvoid(およびメモリが私に役立つ場合char)ポインターにキャストし、再び戻すことができます。また、ランタイムチェックは行われないことに注意してください。間違えた場合は、未定義の動作をお楽しみください!


ただし、キャストは静的に行われます。これが動的型付けの例であるかはわかりません。
osa 14

@osaコードがString foo = (String) barそれを言っているからといって、それがbar実際にaであることを意味しないString。それは実行時に確実にしかわからないので、キャストが「静的に」行われる方法はわかりません。
ドーバル14

私はこれに同意しません。少なくともJavascriptでは、実行時にオブジェクトに新しいメソッドとプロパティを追加できます。C#では、dynamicこれを行うには明示的にオブジェクトを使用する必要があります。プロパティをobject... に追加しようとすると、できません。
アルトゥーロトーレスサンチェス

3

静的および動的型付けの違いはあるとき、コンパイル時間対実行時間を:値の型がチェックされています。値に型が含まれる言語(Javaオブジェクトなど)では、言語が実際に静的な型付けを好む場合でも、常に動的な型付けに頼ることができます。次に、動的に型指定されたメソッドを使用したJavaの例を示します。

void horribleJava(List untypedList) {
  for (Object o : untypedList)
    ((SpecificType) o).frobnicate();
}

実行時に各アイテムのタイプがどのようにチェックされるかに注意してください。静的に型指定された同等のメソッドは次のとおりです。

void goodJava(List<SpecificType> typedList) {
  for (SpecificType o : typedList) {
    o.forbnicate();
  }
}

Cでは、実行時に値(具体的にはポインター)はその型を保持しませんvoid *。すべてのポインターはに相当します。代わりに、変数と式には型があります。動的な型指定を実現するには、型情報を自分で持ち歩く必要があります(たとえば、構造体のフィールドとして)。


1
キャストは、実際的な意味での動的型付けとは見なされません。コンパイル時に型の知識が必要です。実際の検証は実行時まで延期されます。frobnicate最初にを知らない限り、ここでメソッドを呼び出すことはできませんSpecificType
アーロンノート

2
@Aaronaughtしかし、実行時に型チェックを延期すると、これ動的型付けになります。私の例は両方とも、特定の型名を必要とする主格型指定を使用していることに注意してください。あなたは構造的な型付けを考えています、例えば、何らかの方法の存在を必要とするアヒル型付け。軸の構造的対主格および静的対動的タイピングは互いに直交しています(Javaは主格で主に静的です; MLおよびGoは構造的および静的です; Perl、Python、およびRubyは(大部分)構造的で動的です)。
アモン

私が前回のコメントで言ったように、これは私が今まで会ったことのあるプログラマーが本当に気にかけないという理論上の区別です。人々は間違った用語を使用していると断言することができます(実際、元のツイーターはまさにそのような不気味さを狙っていたようです)。実際、その定義は非常に一般的であるため、C#などのラングは実際にコード化されています(つまり、dynamicキーワードで)。等化静的コンパイル時および動的なことはするランタイムだけmuddiesにほとんど水を。
アーロンノート

@Aaronaught:インターフェイスにキャストし、意図した意味でメソッドを実装するクラスが同じインターフェイスを一貫して実装する場合、本質的には実行時のダックタイピングになります。「ダックタイピング」ではメソッド名のみを使用するべきだと主張する人もいますが、「実際の」メソッド名をインターフェイス名にメソッド名を加えたものと考える方が便利だと思います。それ以外の場合は、必要があり[1,2].Add([3,4])[1,2,3,4][1,2,[3,4]]または[4,6]
supercat 14年

@supercat:上記のいずれでもありませんAdd。そのようなメソッドはあいまいになるため、配列を受け入れる配列にはメソッドがないため失敗します。アヒルのタイピングは、わかりやすい型と関数を書くことを許しません。
アーロンノート14年

2

静的タイピングと動的タイピングは、基本的に、タイプのチェック方法に基づいています。静的型付けとは、さまざまな変数または式の型の検証が実際のコード(通常はコンパイラー)に基づいてチェックされるのに対して、動的型システムではこの検証は実行時環境によって実行時にのみ実行されることを意味します。

テキストが参照していると思うのは、型が実際に静的にチェックされても、実行時にも動的にチェックされるということです。Java Reflectionについて正しく言及しました。リフレクションは実行時にのみ行われ、Javaランタイム環境(JVM)はリフレクションが使用されるときに実際に型チェックを実行します。これは基本的に動的型チェックを意味します。


その後、それは正しくありません。C ++、Pascal、Fortranでは---コンパイルされた言語では---型は静的にのみチェックされ、動的にはチェックされません(dynamic_castを使用している場合を除く)。ポインタを使用してメモリに任意のものを書き込むことができますが、誰も型を知りません。したがって、静的な型指定は静的にのみチェックすることを意味し、動的な型指定は実行時にのみチェックすることを意味します。
osa 14

-1

例外は間違っています:Cには重要な動的型システムもあります。単純にチェックしません(「Cは強く型付けされ、弱くチェックされます」)。たとえば、構造体をdoublereinternpret_cast-style)として扱うと、未定義の動作(動的な型エラー)が発生します。


(誰がdownvotedへ- @Thiagoシルバさんのコメントには、同じことを言う)
Elazar
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.