新しいプログラミング言語は動的に型付けされているとよく耳にしますが、言語が動的に型付けされているのか、静的に型付けされていると言えば、それは実際にはどういう意味ですか?
新しいプログラミング言語は動的に型付けされているとよく耳にしますが、言語が動的に型付けされているのか、静的に型付けされていると言えば、それは実際にはどういう意味ですか?
回答:
変数の型がコンパイル時にわかっている場合、言語は静的に型付けされます。一部の言語では、これはプログラマーとして各変数のタイプを指定する必要があることを意味します(例:Java、C、C ++)。他の言語は、何らかの型の型推論、変数の型を推定する型システムの機能を提供します(例:OCaml、Haskell、Scala、Kotlin)
ここでの主な利点は、すべての種類のチェックがコンパイラーによって実行できるため、非常に早い段階で多くの些細なバグが検出されることです。
例:C、C ++、Java、Rust、Go、Scala
タイプが名前付きの変数/フィールド/その他ではなく、ランタイム値に関連付けられている場合、言語は動的に型付けされます。これは、毎回型を指定する必要がないため、プログラマーが少し速く書くことができることを意味します(型推論で静的に型付けされた言語を使用しない限り)。
例:Perl、Ruby、Python、PHP、JavaScript
とにかく静的な型チェックを行うコンパイラがないため、ほとんどのスクリプト言語にはこの機能がありますが、インタプリタが変数の型を誤って解釈することに起因するバグを探している場合があります。幸いなことに、スクリプトは小さい傾向があるため、バグを隠す場所はそれほど多くありません。
ほとんどの動的型付け言語では、型情報を提供できますが、必須ではありません。現在開発中の1つの言語であるRascalは、関数内での動的型付けを可能にする一方で、関数シグネチャの静的型付けを強制するハイブリッドアプローチを採用しています。
静的に型付けされたプログラミング言語は、実行時ではなくコンパイル時に型チェック(つまり、型の制約を検証および適用するプロセス)を実行します。
動的に型付けされたプログラミング言語は、コンパイル時ではなく実行時に型チェックを行います。
静的型付け言語の例は次のとおりです:-Java、C、C ++
動的に型付けされる言語の例は次のとおりです。-Perl、Ruby、Python、PHP、JavaScript
Python(動的に型付けされた)とGo(静的に型付けされた)が型エラーを処理する方法を対比する例を次に示します。
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
Pythonは実行時に型チェックを行うため、次のようになります。
silly(2)
完全に正常に動作し、期待される出力を生成しますHi
。エラーが発生するのは、問題のある行がヒットした場合のみです。
silly(-1)
生産する
TypeError: unsupported operand type(s) for +: 'int' and 'str'
関連する行が実際に実行されたためです。
一方、Goはコンパイル時に型チェックを行います。
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
上記はコンパイルされず、次のエラーが発生します。
invalid operation: "3" + 5 (mismatched types string and int)
runhaskell
、たとえばで解釈できます。
簡単に言えば、静的に型付けされた言語では、変数の型は静的です。つまり、変数を型に設定すると、それを変更することはできません。これは、タイピングが参照する値ではなく変数に関連付けられているためです。
たとえばJavaの場合:
String str = "Hello"; //variable str statically typed as string
str = 5; //would throw an error since str is supposed to be a string only
一方、動的に型付けされた言語では、変数の型は動的です。つまり、変数を型に設定した後で、変数を変更できます。これは、型付けが変数自体ではなく、想定する値に関連付けられているためです。
たとえばPythonの場合:
str = "Hello" # variable str is linked to a string value
str = 5 # now it is linked to an integer value; perfectly OK
したがって、動的に型付けされた言語の変数は、型付きの値への単なる汎用ポインタと考えるのが最善です。
要約すると、型自体は、言語自体ではなく、言語の変数を記述します(または記述する必要がありました)。これは、より良いとして使用されている可能性が静的型付けの変数を持つ言語対動的型付けの変数を持つ言語 IMHO。
静的に型付けされた言語は一般にコンパイルされた言語であるため、コンパイラーは型をチェックします(型は実行時に後で変更することができないため、完全に理解できますか?)。
動的に型付けされた言語は一般的に解釈されるため、使用時に型チェック(存在する場合)が実行時に行われます。これはもちろんパフォーマンスコストをもたらし、動的言語(たとえば、python、ruby、php)が型付きのもの(java、c#など)よりも適切にスケーリングされない理由の1つです。別の見方をすると、静的に型付けされた言語は、初期コストが高くなります。通常、より多くのコード、より難しいコードを記述します。しかし、それは後で報われます。
良い点は、両方が反対側から機能を借用していることです。型付き言語には、c#のジェネリックや動的ライブラリなどのより動的な機能が組み込まれており、動的言語には、Pythonの型注釈やPHPのHACKバリアントなど、より多くの型チェックが含まれています。要求する。
テクノロジーの選択に関しては、どちらの側にも他の側よりも本質的な優位性はありません。最初からより多くの制御をしたいのか、それとも柔軟性を求めたいのかは、好みの問題です。ちょうどその仕事に適したツールを選び、その逆を検討する前に、その逆で何が利用できるかを確認してください。
http://en.wikipedia.org/wiki/Type_system
静的型付け
プログラミング言語は、実行時ではなくコンパイル時に型チェックが実行される場合、静的型付けを使用すると言われています。静的型付けでは、型は値ではなく変数に関連付けられます。静的型付け言語には、Ada、C、C ++、C#、JADE、Java、Fortran、Haskell、ML、Pascal、Perl(スカラー、配列、ハッシュ、サブルーチンの区別に関して)およびScalaが含まれます。静的型付けはプログラム検証の限定された形式です(型の安全性を参照)。したがって、開発サイクルの早い段階で多くの型エラーをキャッチできます。静的型チェッカーは、コンパイル時に決定できる型情報のみを評価しますが、チェックされた条件がプログラムのすべての可能な実行に当てはまることを確認できます。これにより、プログラムが実行されるたびに型チェックを繰り返す必要がなくなります。実行時の型チェックを省略し、他の最適化を有効にすることで、プログラムの実行をより効率的にすることもできます(つまり、メモリを高速化するか、メモリを削減します)。
コンパイル時に型情報を評価し、実行時にのみ利用できる型情報がないため、静的型チェッカーは保守的です。実行時に正常に動作する可能性があるが、静的に適切に型指定されていると判断できない一部のプログラムは拒否されます。たとえば、式が実行時に常にtrueに評価される場合でも、コードを含むプログラムは
if <complex test> then 42 else <type error>
静的分析では、else分岐が行われないと判断できないため、不正な型として拒否されます。[1] 静的型チェッカーの保守的な動作は、まれにfalseと評価される場合に有利です。静的型チェッカーは、ほとんど使用されないコードパスで型エラーを検出できます。静的型チェックがないと、コードカバレッジが100%のコードカバレッジテストでも、そのような型エラーを見つけることができない場合があります。値が作成されるすべての場所と特定の値が使用されるすべての場所の組み合わせを考慮する必要があるため、コードカバレッジテストでは、このような型エラーを検出できない場合があります。
最も広く使用されている静的型付き言語は、正式に型安全ではありません。プログラミング言語の仕様に「抜け穴」があり、プログラマーが静的型チェッカーによって実行される検証を回避するコードを記述できるため、幅広い問題に対処できます。たとえば、JavaおよびほとんどのCスタイル言語には型パンニングがあり、HaskellにはunsafePerformIOなどの機能があります。このような操作は、プログラムの実行時に値の誤った入力が原因で望ましくない動作を引き起こす可能性があるため、実行時に安全ではない場合があります。
動的型付け
プログラミング言語は、その型チェックの大部分がコンパイル時ではなく実行時に実行される場合、動的に型付けされる、または単に「動的」であると言われます。動的型付けでは、型は変数ではなく値に関連付けられます。動的型付け言語には、Groovy、JavaScript、Lisp、Lua、Objective-C、Perl(ユーザー定義型に関して、組み込み型ではない)、PHP、Prolog、Python、Ruby、Smalltalk、Tclが含まれます。静的型付けと比較して、動的型付けは(たとえば、実行時データに基づいてプログラムが型と機能を生成できるようにすることで)より柔軟にできますが、事前の保証は少なくなります。これは、動的に型付けされた言語が、静的型チェッカーによって無効であると判断されるプログラムを受け入れて実行しようとするためです。
動的型付けにより、実行時の型エラーが発生する可能性があります。つまり、実行時に、値に予期しない型があり、その型に意味のない操作が適用されます。この操作は、プログラミングの誤りが発生した場所、つまり、間違ったタイプのデータが本来あるべき場所に渡されなかった場所のかなり後に発生する可能性があります。これにより、バグの特定が困難になります。
動的に型付けされた言語システムは、静的に型付けされたいとこと比較して、ソースコードの「コンパイル時」チェックを少なくします(ただし、たとえば、プログラムが構文的に正しいことをチェックします)。実行時チェックは、動的情報だけでなく、コンパイル中に存在したあらゆる情報を使用できるため、より洗練されている可能性があります。一方、ランタイムチェックは、プログラムの特定の実行で条件が保持されることのみを表明し、プログラムの実行ごとにこれらのチェックが繰り返されます。
動的型付け言語での開発は、多くの場合、ユニットテストなどのプログラミング手法によってサポートされています。テストは、専門的なソフトウェア開発における重要なプラクティスであり、動的に型付けされる言語では特に重要です。実際には、正しいプログラム操作を確実にするために行われるテストは、静的型チェックよりもはるかに広い範囲のエラーを検出できますが、逆に、テストと静的型チェックの両方が検出できるエラーを包括的に検索することはできません。テストはソフトウェアビルドサイクルに組み込むことができます。その場合、プログラムのユーザーがそのようなテストを手動で実行する必要がないため、「コンパイル時」のチェックと見なすことができます。
参考文献
- ピアース、ベンジャミン(2002)。タイプとプログラミング言語。MIT Press。ISBN 0-262-16209-1。
myObject[remoteDataName]
。次に、どのプロパティを選択するか、またはそれが有効なプロパティであるかどうかを知る方法はありません。
「動的に型付けされた」という用語は、残念ながら誤解を招くものです。すべての言語は静的に型付けされ、型は式のプロパティです(一部の人が考える値ではありません)。ただし、一部の言語には1つのタイプしかありません。これらはユニタイプ言語と呼ばれます。そのような言語の1つの例は、型なしラムダ計算です。
型なしラムダ計算では、すべての項がラムダ項であり、ある項に対して実行できる唯一の演算は、それを別の項に適用することです。したがって、すべての操作の結果は常に無限再帰またはラムダ項になりますが、エラーを通知することはありません。
ただし、型なしラムダ計算をプリミティブ数と算術演算で補強する場合、2つのラムダ項を一緒に追加するなど、無意味な演算を実行できます(λx.x) + (λy.y)
。これが起こるときにエラーを通知することだけが正気なことであると主張することができますが、これを行うことができるようにするには、各値がその用語がラムダ用語であるか数値であるかを示すインジケータでタグ付けする必要があります。次に、加算演算子は、両方の引数が数値としてタグ付けされていることを確認し、そうでない場合はエラーを通知します。これらのタグがあることに注意してくださいませんタイプはプログラムのプロパティであり、それらのプログラムによって生成される値ではないため、タイプで。
これを行う単一型言語は動的型付けと呼ばれます。
JavaScript、Python、Rubyなどの言語はすべて型指定されていません。繰り返しになりtypeof
ますが、JavaScript の演算子とtype
Python の関数には誤解を招く名前があります。型ではなく、オペランドに関連付けられたタグを返します。同様にdynamic_cast
、C ++およびinstanceof
Java では、型チェックを行いません。
「ソースコード翻訳時」
「型チェック時」
5 + '3'
GoやPythonなどの強く型付けされた言語での型エラーの例です。 "型強制"-> 2つの型のマージなどの特定のコンテキストで値を変更する機能が許可されていないためです。JavaScriptなどの弱く型付けされた言語は、型エラーをスローしません(結果は'53'
)。
"Static&Compiled"と "Dynamic&Interpreted"の定義は非常に似ていますが、 "型がチェックされるとき"と "ソースコードが変換されるとき"であることに注意してください。
言語がコンパイルされているか解釈されているかに関係なく、同じタイプのエラーが発生します。これらの用語を概念的に分離する必要があります。
動的、解釈済み
def silly(a):
if a > 0:
print 'Hi'
else:
print 5 + '3'
silly(2)
Pythonは解釈され、動的に型付けされるため、実行されているコードの変換と型チェックのみを行います。else
ブロックは実行されませんので、5 + '3'
でも見れることはありません!
静的に型付けされた場合はどうなりますか?
コードが実行される前に型エラーがスローされます。解釈されても、実行前に型チェックを実行します。
コンパイルされた場合はどうなりますか?
else
ブロックは/翻訳、実行時の前に見えたが、それは動的型付けているため、それはエラーをスローしないだろうことでしょう!動的に型付けされた言語は、実行されるまで型をチェックせず、その行は実行されません。
静的、コンパイル済み
package main
import ("fmt"
)
func silly(a int) {
if (a > 0) {
fmt.Println("Hi")
} else {
fmt.Println("3" + 5)
}
}
func main() {
silly(2)
}
実行前に型がチェックされ(静的)、型エラーがすぐにキャッチされます!タイプが解釈された場合、実行前にタイプがチェックされ、同じ結果になります。動的である場合、コンパイル中にコードが確認されても、エラーはスローされません。
コンパイルされた言語は、静的に型付けされている(動的に型付けされている)場合、実行時のパフォーマンスが向上します。型の知識により、機械コードの最適化が可能になります。
静的に型付けされた言語は、実行中に動的に型をチェックする必要がないため(実行前にチェックする)、本質的に実行時のパフォーマンスが向上します。
同様に、コンパイルされた言語は、実行時にコードを「解釈」/翻訳する必要がなく、すでに翻訳されているため、実行時に高速です。
コンパイルされた言語と静的に型付けされた言語の両方で、翻訳と型チェックの実行前にそれぞれ遅延が発生することに注意してください。
静的型付けは、実行中にエラーを見つけるのではなく、早期にエラーをキャッチします(特に長いプログラムに役立ちます)。これは、プログラム内の型エラーを許可せず、変数が型を変更するのを防ぎ、意図しないエラーをさらに防ぐという点で、より「厳密」です。
num = 2
num = '3' // ERROR
動的型付けはより柔軟であり、これを認める人もいます。通常、変数で型を変更できるため、予期しないエラーが発生する可能性があります。
静的に型付けされた言語はコンパイル時に型チェックされ、型は変更できません。(型キャストコメントで可愛くなりません。新しい変数/参照が作成されます)。
動的に型付けされた言語は実行時に型チェックを行い、変数の型は実行時に変更できます。
甘くてシンプルな定義ですが、ニーズに適合します。静的型付き言語は、スコープ全体の型を変数にバインドします(例:SCALA)動的型付き言語は、変数によって参照される実際の値に型をバインドします。
C ++、Javaなどの静的型付け言語とPythonのような動的型付け言語は、変数の型の実行のみが異なります。 静的に型付けされた言語には、変数の静的データ型があります。ここでは、コンパイル中にデータ型がチェックされるため、デバッグがはるかに簡単になります。動的に型付けされた言語では同じことが行われませんが、プログラムを実行するデータ型がチェックされるためデバッグは少し難しいです。
さらに、それらには非常に小さな違いがあり、強く型付けされた言語と弱く型付けされた言語に関連付けることができます。強く型付けされた言語では、ある型を別の型として使用することはできません。CおよびC ++ ...弱く型付けされた言語では、たとえば.python
静的型付け
タイプは実行前にチェックされるので、間違いをより早く見つけることができます。
例= c ++
動的に型付け
タイプは実行中にチェックされます。
例= Python
静的型付け: JavaやScalaなどの言語は静的型付けです。
変数は、コードで使用する前に定義および初期化する必要があります。
例として。int x; x = 10;
System.out.println(x);
動的型付け: Perlは動的型付け言語です。
変数は、コードで使用する前に初期化する必要はありません。
y = 10; コードの後半でこの変数を使用する
$
)、配列(@
)、ハッシュ(%
)の3つの型があります。Perlの変数の型はコンパイル時に認識され、残りの変数の存続期間中同じままです。