静的型言語と比較した動的型言語の利点と制限は何ですか?
参照:動的言語の愛情とは何か(はるかに議論の多いスレッド...)
静的型言語と比較した動的型言語の利点と制限は何ですか?
参照:動的言語の愛情とは何か(はるかに議論の多いスレッド...)
回答:
インタプリタが型と型変換を推定する機能は、開発時間を短縮しますが、コンパイル時に静的型付けされた言語では取得できないランタイムエラーを引き起こす可能性もあります。しかし、どちらが優れているか(それが常に真実であっても)は、最近(そして長い間)コミュニティで激しく議論されています。
この問題についての良い見解は、可能な場合は静的型付け、必要な場合は動的型付けから:MicrosoftのErik MeijerとPeter Draytonによるプログラミング言語間の冷戦の終焉:
静的型付けの擁護者は、静的型付けの利点には、プログラミングの誤りの早期検出(たとえば、ブール値への整数の追加の防止)、型シグネチャの形式でのより良いドキュメント(たとえば、名前を解決するときに引数の数と型を組み込む)などが含まれると主張しています。コンパイラーの最適化(例:レシーバーの正確なタイプが静的にわかっている場合に仮想呼び出しを直接呼び出しに置き換える)、実行時の効率を向上(例:すべての値が動的なタイプを保持する必要がない)、および設計時の開発者エクスペリエンスの向上(例:レシーバーのタイプ。IDEは、該当するすべてのメンバーのドロップダウンメニューを表示できます。静的型付けの狂信者は、「適切に型付けされたプログラムはうまくいかない」と私たちに信じさせようとします。これは確かに印象的に聞こえますが、それはかなり空虚な声明です。静的型チェックは、プログラムの実行時の動作をコンパイル時に抽象化したものであるため、必ずしも部分的に健全で不完全です。これは、型チェッカーによって追跡されないプロパティが原因でプログラムがまだ失敗する可能性があること、および、失敗することはないが型チェックできないプログラムがあることを意味します。静的型付けを部分的でなく完全にするための衝動は、「ファントム型」[11]や「ぐらついた型」[10]などの概念に見られるように、型システムを過度に複雑でエキゾチックなものにします。これは、ボールとチェーンを足に結び付けてマラソンを走ろうとするようなもので、ファーストマイル後に救済されたにもかかわらず、ほぼ達成したことを大喜びで叫びます。静的型チェックは、プログラムの実行時の動作をコンパイル時に抽象化したものであるため、必ずしも部分的に健全で不完全です。これは、型チェッカーによって追跡されないプロパティが原因でプログラムがまだ失敗する可能性があること、および、失敗することはないが型チェックできないプログラムがあることを意味します。「ファントム型」[11]や「ゆらぎ型」[10]などの概念に見られるように、静的型付けを部分的でなく完全なものにする衝動は、型システムを過度に複雑でエキゾチックなものにします。これは、ボールとチェーンを足に結び付けてマラソンを走ろうとするようなもので、ファーストマイル後に救済されたにもかかわらず、ほぼ達成したことを大喜びで叫びます。静的型チェックは、プログラムの実行時の動作をコンパイル時に抽象化したものであるため、必ずしも部分的に健全で不完全です。これは、型チェッカーによって追跡されないプロパティが原因でプログラムがまだ失敗する可能性があること、および、失敗することはないが型チェックできないプログラムがあることを意味します。静的型付けを部分的でなく完全にするための衝動は、「ファントム型」[11]や「ぐらついた型」[10]などの概念に見られるように、型システムを過度に複雑でエキゾチックなものにします。これは、ボールとチェーンを足に結び付けてマラソンを走ろうとするようなもので、ファーストマイル後に救済されたにもかかわらず、ほぼ達成したことを大喜びで叫びます。したがって、それは必然的に部分的にのみ健全で不完全です。これは、型チェッカーによって追跡されないプロパティが原因でプログラムがまだ失敗する可能性があること、および、失敗することはないが型チェックできないプログラムがあることを意味します。静的型付けを部分的でなく完全にするための衝動は、「ファントム型」[11]や「ぐらついた型」[10]などの概念に見られるように、型システムを過度に複雑でエキゾチックなものにします。これは、ボールとチェーンを足に結び付けてマラソンを走ろうとするようなもので、ファーストマイル後に救済されたにもかかわらず、ほぼ達成したことを大喜びで叫びます。したがって、それは必然的に部分的にのみ健全で不完全です。これは、型チェッカーによって追跡されないプロパティが原因でプログラムがまだ失敗する可能性があること、および、失敗することはないが型チェックできないプログラムがあることを意味します。静的型付けを部分的でなく完全にするための衝動は、「ファントム型」[11]や「ぐらついた型」[10]などの概念に見られるように、型システムを過度に複雑でエキゾチックなものにします。これは、ボールとチェーンを足に結び付けてマラソンを走ろうとするようなもので、ファーストマイル後に救済されたにもかかわらず、ほぼ達成したことを大喜びで叫びます。そして、失敗することはないが型チェックができないプログラムがある。静的型付けを部分的でなく完全にするための衝動は、「ファントム型」[11]や「ぐらついた型」[10]などの概念に見られるように、型システムを過度に複雑でエキゾチックなものにします。これは、ボールとチェーンを足に結び付けてマラソンを走ろうとするようなもので、ファーストマイル後に救済されたにもかかわらず、ほぼ達成したことを大喜びで叫びます。そして、失敗することはないが型チェックができないプログラムがある。「ファントム型」[11]や「ゆらぎ型」[10]などの概念に見られるように、静的型付けを部分的でなく完全なものにする衝動は、型システムを過度に複雑でエキゾチックなものにします。これは、ボールとチェーンを足に結び付けてマラソンを走ろうとするようなもので、ファーストマイル後に救済されたにもかかわらず、ほぼ達成したことを大喜びで叫びます。
動的型付け言語の擁護者は、静的型付けは厳格すぎ、動的言語の柔らかさにより、要件が変化する、または不明なプロトタイピングシステム、または予測不能に変化する他のシステムと相互作用する(データおよびアプリケーションの統合)には理想的であると主張しています。もちろん、動的型付け言語は、メソッドインターセプト、動的ロード、モバイルコード、ランタイムリフレクションなどの真に動的なプログラム動作を処理するために不可欠です。スクリプトに関するすべての論文[16]の母として、John Ousterhoutは、静的型付けシステムプログラミング言語は、動的に型付けされたスクリプト言語よりもコードの再利用性、冗長性、安全性、表現力を低下させます。この議論は、動的に型付けされたスクリプト言語の多くの支持者によって文字通りオウムされています。これは誤りであり、宣言型プログラミングの本質は代入を排除していると主張するのと同じカテゴリーに分類されると私たちは主張します。あるいは、ジョン・ヒューズが言っているように[8]、機能を省いて言語をより強力にすることは論理的に不可能です。すべての型チェックをランタイムに遅らせることは良いことであるという事実を守ることは、開発プロセスのできるだけ早い段階でエラーをキャッチする必要があるという事実をもって、ダチョウの戦術を実行しています。機能を省略して言語をより強力にすることは、論理的に不可能です。すべての型チェックを実行時まで遅らせることは良いことであるという事実を守ることは、開発プロセスのできるだけ早い段階でエラーをキャッチする必要があるという事実をもってダチョウの戦術を演じることです。機能を省略して言語をより強力にすることは、論理的に不可能です。すべての型チェックを実行時まで遅らせることは良いことであるという事実を守ることは、開発プロセスのできるだけ早い段階でエラーをキャッチする必要があるという事実をもってダチョウの戦術を演じることです。
静的型システムは、特定のエラーを静的に排除し、プログラムを実行せずに検査し、特定の点で健全性を証明しようとします。一部の型システムは、他の型システムよりも多くのエラーをキャッチできます。たとえば、C#は、適切に使用するとnullポインター例外を排除できますが、Javaにはそのような機能はありません。Twelfには、証明が終了することを実際に保証する型システムがあり、停止問題を「解決」します。
ただし、完璧な型システムはありません。特定の種類のエラーを排除するために、規則に違反する特定の完全に有効なプログラムも拒否する必要があります。Twelfが停止の問題を実際に解決しないのはこのためです。奇妙な方法で終了する完全に有効な多数の証明を破棄することで、Twelfはそれを回避します。同様に、Javaの型システムはPersistentVector
、異種混合配列を使用しているため、Clojureの実装を拒否します。実行時に機能しますが、型システムは検証できません。
そのため、ほとんどの型システムには、静的チェッカーをオーバーライドする方法である「エスケープ」が用意されています。ほとんどの言語では、これらはキャストの形式を取りますが、一部(C#やHaskellなど)には、「安全でない」とマークされたモード全体があります。
主観的には、静的型付けが好きです。静的型システムは適切に実装され(ヒント:Javaではありません)、本番システムがクラッシュする前にエラーを取り除くのに非常に役立ちます。動的に型付けされた言語は、多くの場合単体テストを必要とする傾向があり、多くの場合面倒です。また、静的型付け言語には、動的型システムでは不可能または安全でない特定の機能がある場合があります(暗黙の変換が思い浮かびます)。それはすべて要件と主観的な好みの問題です。Rubyで次のEclipseをビルドするのは、Javaを使用してアセンブリでバックアップスクリプトを作成するか、カーネルにパッチを当てるのと同じです。
ああ、「xタイピングはyタイピングよりも10倍生産性が高い」と言う人は単に煙を吹いています。多くの場合、動的型付けはより速く「感じる」ことができますが、実際に豪華なアプリケーションを実行しようとすると、根拠が失われます。同様に、静的型付けは完璧なセーフティネットのように思えるかもしれませんが、Javaでのより複雑なジェネリック型定義のいくつかを見ると、ほとんどの開発者が目をくらませるのに慌てています。型システムと生産性があっても、特効薬はありません。
最後の注意:静的型付けと動的型付けを比較するときにパフォーマンスについて心配する必要はありません。V8やTraceMonkeyなどの最新のJITは、静的言語のパフォーマンスに非常に近づいています。また、Javaが本質的に動的な中間言語に実際にコンパイルされるという事実は、ほとんどの場合、動的型付けは一部の人々がそうすることを明らかにした巨大なパフォーマンスキラーではないというヒントになるはずです。
dadd
オペランドがdouble
sであることを事前に知っているため、コンパイラーは次のような命令を選択するため、それらを網羅する追加のランタイムチェックは必要ありません。
まあ、どちらも非常に、非常に非常に非常に非常に誤解されており、また2つの完全に異なるものです。それらは相互に排他的ではありません。
静的型は、言語の文法の制限です。静的に型付けされた言語は、厳密にはコンテキストフリーではないと言えます。単純な真実は、すべてのデータを単純にビットベクトルとして処理しない文脈自由文法で言語をまともな形で表現することが不便になることです。静的型システムは、もしあれば言語の文法の一部であり、コンテキストフリーの文法よりも制限するだけです。したがって、文法チェックは実際にはソース上の2つのパスで行われます。静的型は型理論の数学的概念に対応し、数学の型理論はいくつかの式の合法性を制限するだけです。3 + [4,7]
数学では言えませんが、これは型理論のせいです。
したがって、静的型は理論的な観点から「エラーを防ぐ」方法ではなく、文法の制限です。実際、+、3、および間隔に通常のセット理論的定義がある場合、型システムを削除すると、セットで3 + [4,7]
あるかなり明確な結果が得られます。「実行時型エラー」は理論的には存在しません。型システムの実用的な用途は、人間にとって意味のない操作を防ぐことです。もちろん、操作はビットのシフトと操作にすぎません。
これの難点は、型システムは、そのような操作が実行されるかどうか、実行が許可されるかどうかを決定できないことです。同様に、すべての可能なプログラムのセットを、「タイプエラー」が発生するプログラムと発生しないプログラムに正確に分割します。次の2つのことしかできません。
1:プログラムで型エラーが発生
することを証明する2:プログラムで型エラーが発生しないことを証明する
これは私が矛盾しているように思えるかもしれません。しかし、CまたはJavaの型チェッカーが行うことは、プログラムを「文法に反する」、または2で成功できない場合に「型エラー」と呼ぶことで、プログラムを拒否することです。それらが発生しないことを証明することはできません。それが発生しないという意味ではなく、それを証明できないという意味です。型エラーが発生しないプログラムは、コンパイラーで証明できないという理由だけで拒否される可能性があります。存在する簡単な例if(1) a = 3; else a = "string";
、確かに常にtrueであるため、else-branchはプログラムで実行されることはなく、型エラーは発生しません。ただし、これらのケースを一般的な方法で証明することはできないため、拒否されます。これは多くの静的型付け言語の主な弱点です。自分自身を保護する上で、必要のない場合は必ず保護されます。
しかし、一般に信じられていることとは逆に、原則1で機能する静的型付き言語もあります。これらは、型エラーの原因になることを証明できるすべてのプログラムを単に拒否し、そうでないすべてのプログラムを渡します。そのため、型エラーのあるプログラムを許可する可能性があります。良い例として、Typed Racketがあります。動的型と静的型のハイブリッドです。そして、このシステムで両方の長所を利用できると主張する人もいます。
静的型付けのもう1つの利点は、型がコンパイル時に認識されるため、コンパイラーがこれを使用できることです。Javaで"string" + "string"
またはの場合、最後のテキスト内の3 + 3
両方の+
トークンが完全に異なる操作とデータを表す場合、コンパイラーはタイプのみからどちらを選択するかを認識しています。
ここで、私は非常に物議を醸す声明を出して、私と一緒に言いましょう。「動的型付け」は存在しません。
非常に論争の音が、それは本当だ、動的型付け言語は理論的な視点からある型なし。それらは静的型付け言語であり、型は1つだけです。簡単に言えば、実際には文脈自由文法によって実際に文法的に生成された言語です。
なぜ型がないのですか?すべての操作が定義され、すべてのオペラントで許可されているため、正確に「ランタイムタイプエラー」とは何ですか?それは純粋に副作用の理論的な例からのものです。やった場合はprint("string")
文字列を出力しているが操作されるようにされ、その後length(3)
、前者は書き込みの副作用があるstring
標準出力にし、後者は単にerror: function 'length' expects array as argument.
、それはそれです。理論的には、動的型付け言語などはありません。彼らは型付けされていません
はい、「動的型付け」言語の明らかな利点は表現力です。型システムは表現力の制限にすぎません。そして一般的に、型システムを備えた言語は、型システムが単に無視された場合に許可されないすべての操作に対して実際に定義された結果を持ち、その結果は人間にとって意味がありません。型システムを適用した後、多くの言語はチューリングの完全性を失います。
明らかな欠点は、人間には無意味な結果を生成する操作が発生する可能性があるという事実です。これを防ぐために、動的に型付けされた言語は通常、これらの操作を再定義しますが、無意味な結果を生成するのではなく、エラーを書き出してプログラムを完全に停止するという副作用を持つように再定義します。これはまったく「エラー」ではありません。実際、言語仕様は通常これを暗示しています。これは、理論的な観点から文字列を出力するのと同じくらい言語の動作です。したがって、型システムはプログラマーにコードの流れについて推論させ、これが起こらないようにします。または実際に、その理由は、それはそれを行いますデバッグは、「エラー」ではなく、言語の明確に定義されたプロパティであることを示しており、デバッグの際に便利です。実際、ほとんどの言語が持っている「動的型付け」の唯一の名残は、ゼロによる除算から保護しています。これが動的型付けであり、型はありません。それ以外の型はありません。ゼロは他のすべての数値とは異なる型です。人々が「タイプ」と呼ぶものは、配列の長さや文字列の最初の文字など、データのもう1つのプロパティです。また、動的に型付けされる言語の多くでは、のようなものを書き出すこともできます"error: the first character of this string should be a 'z'"
。
もう1つは、動的に型付けされた言語には実行時に使用可能な型があり、通常はそれをチェックして処理し、それから決定できるということです。もちろん、理論的には、配列の最初の文字にアクセスしてそれが何であるかを確認することと同じです。実際、独自の動的Cを作成し、long long intのような1つの型のみを使用し、その最初の8ビットを使用して「型」を格納し、それに応じてチェックして浮動小数点または整数の加算を実行する関数を書き込むことができます。1つのタイプの静的型付き言語、または動的言語があります。
実際、これはすべて静的に型付けされた言語が商用ソフトウェアの記述のコンテキストで使用されるのに対し、動的に型付けされた言語は、いくつかの問題の解決といくつかのタスクの自動化のコンテキストで使用される傾向があります。静的に型付けされた言語でコードを書くことは、時間がかかるだけで面倒です。それは、あなたがわかったことがうまくいくとわかっていることはできませんが、型システムは、自分が犯していないエラーから自分を守ってくれるからです。多くのプログラマーは、システム内にあるためにこれを行うことにさえ気づいていませんが、静的言語でコーディングする場合、タイプシステムではうまくいかないことを実行できないという事実を回避することがよくあります。それがうまくいかないことを証明することはできません。
私が指摘したように、「静的に型付けされた」とは、一般にケース2を意味し、無罪であることが証明されるまで有罪となります。しかし、型理論から型システムをまったく導き出さない言語の中には、ルール1を使用するものがあります。だから、多分タイプドラケットはあなたのためです。
また、まあ、もっと不条理で極端な例として、私は現在「型」が本当に配列の最初の文字である言語を実装しています、それらはデータですタイプとデータム、それ自体がタイプとして存在する唯一のデータム。タイプは有限または静的に制限されていませんが、ランタイム情報に基づいて新しいタイプが生成される場合があります。
おそらく、動的型付けの単一の最大の「利点」は、より浅い学習曲線です。学習する型システムはなく、型制約などのコーナーケースの重要な構文もありません。これにより、より多くの人が動的型付けを利用できるようになり、洗練された静的型システムが手の届かない多くの人が実行可能になります。その結果、動的型付けは、教育(たとえば、MITのScheme / Python)および非プログラマー向けのドメイン固有言語(たとえば、Mathematica)のコンテキストで普及しました。動的言語は、競争がほとんどない、またはまったくないニッチ市場でも人気を博しています(例:Javascript)。
最も簡潔な動的型付け言語(Perl、APL、J、K、Mathematicaなど)はドメイン固有であり、それらが設計されたニッチの最も簡潔な汎用静的型言語(OCamlなど)よりもはるかに簡潔にすることができます。。
動的型付けの主な欠点は次のとおりです。
ランタイム型エラー。
同じレベルの正確さを達成することは非常に困難であるか、実際には不可能であり、はるかに多くのテストを必要とします。
コンパイラで検証されたドキュメントはありません。
パフォーマンスの低下(通常は実行時ですが、代わりにコンパイル時(例:Stalin Scheme))と、高度な最適化に依存しているために予測できないパフォーマンス。
個人的に、私は動的言語で育ちましたが、他に実行可能なオプションがない限り、専門家として40フィートのポールでそれらに触れることはありません。
Artimaのタイピングから:強いvs.弱い、静的vs.動的な記事:
強い型付けは、不一致の型間の操作の混合を防ぎます。タイプを混在させるには、明示的な変換を使用する必要があります
弱い型付けとは、明示的な変換なしに型を混在させることができることを意味します
Pascal Costanzaの論文、動的型と静的型の比較—パターンベースの分析(PDF)で、動的型よりも静的型の方がエラーが発生しやすいと主張しています。一部の静的型付け言語では、「正しいこと」を行うために手動で動的型付けをエミュレートする必要があります。Lambda the Ultimateで議論されています。
状況によります。動的型付けシステムだけでなく、強い型付けシステムにも適切な多くの利点があります。動的型言語のフローの方が速いと思います。動的言語は、クラス属性やコンパイラーがコードで何が行われているのかを考えることに拘束されません。少し自由があります。さらに、動的言語は通常、より表現力があり、結果としてコードが少なくなり、優れています。これにも関わらず、エラーが発生しやすく、問題もあり、単体テストのカバーに依存します。これは動的言語を使用した簡単なプロトタイプですが、メンテナンスが悪夢になる可能性があります。
静的型付けシステムに対する主な利点は、IDEサポートと確実に静的コードのアナライザーです。コードを変更するたびに、コードに自信を持つことができます。メンテナンスはそんな道具でケーキの安らぎ。