また、一方が他方を暗示していますか?
また、一方が他方を暗示していますか?
回答:
強く型付けされた言語と静的に型付けされた言語の違いは何ですか?
静的に型付けされた言語の型システムは、コンパイル時に実装(コンパイラーまたはインタープリター)によってチェックされます。型チェックは一部のプログラムを拒否し、チェックに合格したプログラムは通常、いくつかの保証が付いています。たとえば、コンパイラーは、浮動小数点数に対して整数演算命令を使用しないことを保証します。
「強く型付けされた」が何を意味するかについての実際の合意はありませんが、専門文献で最も広く使用されている定義は、「強く型付けされた」言語では、プログラマーが型システムによって課された制限を回避することができないということです。この用語は、ほとんどの場合、静的型付け言語を表すために使用されます。
静的型付けの反対は「動的型付け」です。つまり、
たとえば、動的に型付けされる言語であるLuaには、文字列型、数値型、ブール型などがあります。Luaのでは、すべての値がに属し、正確に一つのタイプが、これは、すべての動的型付け言語の要件ではありません。Luaでは、2つの文字列を連結することは許可されていますが、文字列とブール値を連結することは許可されていません。
「強く型付けされた」の反対は「弱い型付け」です。つまり、型システムを回避できます。ポインタ型はキャストするだけで他のポインタ型に変換できるため、Cの型は弱いことで有名です。Pascalは強く型付けされることを意図していたが、設計の見落とし(タグなしのバリアントレコード)により型システムに抜け穴ができたため、技術的には型付けが弱い。真に強く型付けされた言語の例には、CLU、標準ML、Haskellなどがあります。標準MLは、言語が広く導入された後に発見された型システムの抜け穴を取り除くために、実際にいくつかの改訂を受けました。
全体として、「強い」と「弱い」について話すことはそれほど有益ではないことがわかります。型システムに抜け穴があるかどうかは、抜け穴の正確な数と性質、実際に出現する可能性、および抜け穴を悪用した場合の結果よりも重要ではありません。実際には、「強い」と「弱い」という用語を完全に避けることが最善です。
アマチュアはしばしばそれらを「静的」および「動的」と融合させます。
どうやら「弱い型付け」は、暗黙の変換の相対的な有病率または不在について話すために一部の人によって使用されています。
専門家は、用語が何を意味するのか正確に合意することはできません。
全体として、視聴者に情報を伝えたり、啓蒙したりすることはほとんどありません。
悲しい真実は、型システムに関しては、「強い」と「弱い」は技術的な意味で普遍的に合意されていないということです。 型システムの相対的な強さを議論したい場合は、何が保証されて何が提供されないかを正確に議論する方が良いです。たとえば、次のような質問をすることをお勧めします。「特定の型(またはクラス)のすべての値は、その型のコンストラクターの1つを呼び出すことによって作成されたことが保証されていますか?」Cでは答えはノーです。CLU、F#、およびHaskellでは、それはイエスです。C ++についてはわかりません。知りたいのですが。
対照的に、静的型付けとは、プログラムが実行される前にチェックされ、プログラムが開始される前に拒否される可能性があることを意味します。 動的型付けとは、実行中に値の型がチェックされることを意味します。型付けが適切でないと、プログラムが停止したり、実行時にエラーを通知したりすることがあります。静的型付けの主な理由は、そのような「動的型エラー」が発生する可能性のあるプログラムを除外するためです。
一方が他方を示唆していますか?
教育レベルでは、「強い」という言葉は実際には何の意味もないので、違います。しかし実際には、人々はほとんど常に次の2つのことのいずれかを行います。
彼らは(誤って)「静的」と「動的」を意味する「強い」と「弱い」を使用します。その場合、彼らは(誤って)「強く型付けされた」と「静的に型付けされた」を交換可能に使用しています。
静的型システムのプロパティを比較するために、「強い」と「弱い」を使用します。「強い」または「弱い」動的型システムについて誰かが話すのを聞くのは非常にまれです。型システムがまったくないFORTHを除いて、動的に型付けされた言語で型システムを破壊できるとは思えません。定義上、これらのチェックは実行エンジンに組み込まれ、すべての操作は実行前に正常性がチェックされます。
どちらの方法でも、人が「強く型付けされた」言語を呼び出す場合、その人は静的に型付けされた言語について話している可能性が非常に高いです。
これは誤解されることが多いので、片付けておきます。
静的型付けは、型が変数にバインドされる場所です。タイプはコンパイル時にチェックされます。
動的型付けは、型が値にバインドされる場所です。タイプは実行時にチェックされます。
たとえばJavaでは次のようになります。
String s = "abcd";
s
「永久に」になりますString
。その存続期間中は、異なるを指す場合があります(Javaでの参照であるString
ためs
)。null
値を持つ場合がありますが、Integer
またはを参照することはありませんList
。それは静的型付けです。
PHPの場合:
$s = "abcd"; // $s is a string
$s = 123; // $s is now an integer
$s = array(1, 2, 3); // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class
それは動的なタイピングです。
(アラートを編集!)
強いタイピングとは、広く合意された意味のないフレーズです。この用語を静的型付け以外のことを意味するために使用するほとんどのプログラマーは、コンパイラーによって強制される型の規律があることを意味するためにこれを使用します。たとえば、CLUには強力な型システムがあり、タイプによって提供されるコンストラクターを使用しない限り、クライアントコードは抽象型の値を作成できません。Cはやや強力な型システムを持っていますが、プログラムは常にあるポインタ型の値を別のポインタ型の値にキャストできるため、ある程度「破壊」される可能性があります。したがって、たとえばCでは、によって返された値を取り、malloc()
陽気ににキャストすることFILE*
ができ、コンパイラーはユーザーを止めようとはしません。
(元の答えは、「実行時に型を変更しない」という値について何かを述べていました。私は多くの言語デザイナーやコンパイラー作成者を知っており、実行時に型を変更する値について話している人は知りません。これは「強い更新の問題」として知られているシステム)
弱いタイピングは、コンパイラーが型付けの規律を強制しないこと、またはおそらく強制が簡単に覆される可能性があることを意味します。
この回答のオリジナルは、弱い型付けと暗黙的な変換を融合させました(「暗黙的なプロモーション」とも呼ばれます)。たとえば、Javaの場合:
String s = "abc" + 123; // "abc123";
これは、暗黙的なプロモーションの例のコードです。123は、と連結される前に暗黙的に文字列に変換されます"abc"
。Javaコンパイラがそのコードを次のように書き換えていると主張できます。
String s = "abc" + new Integer(123).toString();
古典的なPHPの「次で始まる」問題を考えてみます。
if (strpos('abcdef', 'abc') == false) {
// not found
}
ここでのエラーは、strpos()
0である一致のインデックスを返すことです。0はブール値に強制変換されるfalse
ため、条件は実際にはtrueです。解決策は、暗黙的な変換を回避する===
代わりにを使用することです==
。
この例は、暗黙の変換と動的型付けの組み合わせがプログラマを迷わせる方法を示しています。
Rubyと比較してください。
val = "abc" + 123
Rubyではオブジェクト 123がたまたまメソッドに渡されただけで暗黙的に変換されないため、これはランタイムエラー+
です。Rubyでは、プログラマは変換を明示的にする必要があります。
val = "abc" + 123.to_s
PHPとRubyの比較は、ここでの良い例です。どちらも動的に型付けされた言語ですが、PHPには多くの暗黙の変換があり、Ruby(おそらく、それに慣れていない場合は驚くべきこと)にはありません。
ここでのポイントは、静的/動的軸が強軸/弱軸から独立していることです。強い型と弱い型が明確に定義されていないだけでなく、強い型と弱い型が何を意味するかについて正確なコンセンサスがないため、人々はおそらくそれらを混乱させます。このため、強い/弱いタイピングは、黒や白ではなく、灰色の濃淡で行われます。
だからあなたの質問に答える:これを見るのがほとんど正しい別の方法は、静的型付けはコンパイル時の型安全であり、強い型付けはランタイム型安全であると言うことです。
これは、静的に型付けされた言語の変数には、宣言する必要のある型があり、コンパイル時にチェックできるためです。強く型付けされた言語には、実行時に型を持つ値があり、プログラマが動的チェックなしに型システムを破壊することは困難です。
ただし、言語は静的/強力、静的/弱、動的/強力、動的/弱のいずれかになる可能性があることを理解することが重要です。
"abc" + 123
Rubyのコンパイルエラーではなく、実行時エラーです。コンパイルエラーの場合、ルビは静的に型付けされます。
どちらも2つの異なる軸上の極です。
強く型付けされたとは、aがある型から別の型に自動的に変換されないことを意味します。弱い型付けはその逆です。Perlは、文字列"123"
を自動的にintに変換することにより、数値コンテキストのように使用できます123
。Pythonのような強く型付けされた言語はこれを行いません。
静的型付けとは、コンパイラがコンパイル時に各変数の型を計算することを意味します。動的に型付けされた言語は、実行時に変数の型のみを把握します。
強く型付けされているとは、型間の変換の間に制限があることを意味します。静的型付けとは、型が動的でないことを意味します。一度作成された変数の型を変更することはできません。
Data Coercionは必ずしも弱い型付けを意味するわけではありません。それは、そのシンタクシカルな砂糖が時々あるからです。
上記のJavaが弱い型付けの例
String s = "abc" + 123;
それは本当にやっているので、弱く型付けされた例ではありません:
String s = "abc" + new Integer(123).toString()
新しいオブジェクトを構築する場合も、データ型変換は弱く型付けされません。Javaは、弱く型付けされた非常に悪い例です(そして、適切に反映されている言語は、弱く型付けされていない可能性が高いです)。言語のランタイムは型が何であるかを常に知っているからです(例外はネイティブ型かもしれません)。
これはCとは異なります。Cは弱い型付けの最も良い例の1つです。ランタイムは、4バイトが整数、構造体、ポインター、または4文字であるかどうかを知りません。
言語のランタイムは、弱く型付けされているかどうかを本当に定義します。
編集: さらに考えた後、ランタイムは厳密に型指定されたシステムになるためにランタイムシステムですべての型を具体化する必要がないため、これは必ずしも正しくありません。HaskellとMLには完全な静的分析があり、ランタイムから型情報が省略される可能性があります。
回答はすでに上記で与えられています。強力な概念と週の概念、静的な概念と動的な概念を区別しようとします。
強く型付け:ある型から別の型に自動的に変換されません
GoまたはPythonでは、厳密に型指定された言語のように、「2」+ 8は「型強制」を許可しないため、型エラーが発生します。
弱く(ゆるく) 型付け:ある型から別の型に自動的に変換されます: JavaScriptやPerlなどの弱く型付けされた言語はエラーをスローせず、この場合、JavaScriptは「28」となり、perlは10になります。
Perlの例:
my $a = "2" + 8;
print $a,"\n";
それをmain.plに保存して実行します perl main.pl
すると、出力10が得られます。
プログラミングでは、プログラマーは、変数タイプがチェックされるポイントに関して静的型付けと動的型付けを定義します。静的型付き言語は、型チェックがコンパイル時に行われる言語であり、動的型付き言語は、型チェックが実行時に行われる言語です。
これはどういう意味ですか?
Goでは、実行前に入力されたチェックを行います(静的チェック)。つまり、実行中のコードを変換して型チェックするだけでなく、すべてのコードをスキャンし、コードが実行される前に型エラーがスローされます。例えば、
package main
import "fmt"
func foo(a int) {
if (a > 0) {
fmt.Println("I am feeling lucky (maybe).")
} else {
fmt.Println("2" + 8)
}
}
func main() {
foo(2)
}
このファイルをmain.goに保存して実行すると、コンパイル失敗のメッセージが表示されます。
go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)
ただし、このケースはPythonでは無効です。たとえば、次のコードブロックは最初のfoo(2)呼び出しに対して実行され、2番目のfoo(0)呼び出しに対して失敗します。これは、Pythonが動的に型付けされているため、実行されているコードの変換と型チェックのみを行うためです。elseブロックはfoo(2)では決して実行されないため、「2」+ 8は決して見られず、foo(0)呼び出しではそのブロックを実行しようとして失敗します。
def foo(a):
if a > 0:
print 'I am feeling lucky.'
else:
print "2" + 8
foo(2)
foo(0)
次の出力が表示されます
python main.py
I am feeling lucky.
Traceback (most recent call last):
File "pyth.py", line 7, in <module>
foo(0)
File "pyth.py", line 5, in foo
print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects
一方は他方を意味しません。言語を静的にするには型付けされるということは、すべての変数の型がコンパイル時に既知または推論されることを意味します。
強く型付けされた言語を使用すると、別のように、1つのタイプを使用することはできません。Cは弱く型付けされた言語であり、強く型付けされた言語が許可しないものの良い例です。Cでは、間違ったタイプのデータ要素を渡すことができ、文句はありません。強く型付けされた言語ではできません。
強い型付けとは、おそらく変数が明確に定義された型を持ち、式で異なる型の変数を結合することに関して厳しい規則があることを意味します。たとえば、Aが整数でBが浮動小数点の場合、A + Bに関する厳密な規則は、Aが浮動小数点にキャストされ、結果が浮動小数点として返されることです。Aが整数でBが文字列である場合、厳密な規則はA + Bが無効であることです。
静的型付けとは、おそらく型がコンパイル時に割り当てられ(またはコンパイルされていない言語では同等)、プログラムの実行中に変更できないことを意味します。
これらの分類は相互に排他的ではないことに注意してください。実際、これらは一緒に頻繁に発生すると予想されます。多くの強く型付けされた言語も静的に型付けされます。
そして、私が「おそらく」という言葉を使用するのは、これらの用語の普遍的に受け入れられている定義がないためです。あなたはこれまでの答えからすでに見てきたように。