ほとんどのコーディング言語(すべてではないにしても)では、変数を宣言する必要があります。たとえば、C#では、その数値フィールドが
int PhoneNumber
私は、通常の英語を使用している場合は、私は宣言する必要はありませんPhoneNumberようintにそれを使用します。たとえば、友人のサムに電話番号を教えてもらったら、
「サムが電話番号を教えて」
言わない
「Char(20)サムがint phoneNumberをくれた」
データ型を指定する必要があるのはなぜですか?
ほとんどのコーディング言語(すべてではないにしても)では、変数を宣言する必要があります。たとえば、C#では、その数値フィールドが
int PhoneNumber
私は、通常の英語を使用している場合は、私は宣言する必要はありませんPhoneNumberようintにそれを使用します。たとえば、友人のサムに電話番号を教えてもらったら、
「サムが電話番号を教えて」
言わない
「Char(20)サムがint phoneNumberをくれた」
データ型を指定する必要があるのはなぜですか?
回答:
ほとんどのコーディング言語(すべてではないにしても)では、変数を宣言する必要があります。
[…]
データ型を指定する必要があるのはなぜですか?
これらは2つの独立した質問です。
ちなみに、両方の答えは、「そうではありません」です。
型を宣言する必要のない静的型付けプログラミング言語がたくさんあります。コンパイラーは、周囲のコンテキストと使用法から型を推測できます。
たとえば、Scalaでは次のように言うことができます
val age: Int = 23
またはあなたは言うことができます
val age = 23
2つはまったく同じです。コンパイラーはInt、初期化式から型を推測します23。
同様に、C♯では、これらのいずれかを言うことができ、両方ともまったく同じことを意味します。
int age = 23;
var age = 23;
この機能は型推論と呼ばれ、ScalaとC♯以外の多くの言語には、Haskell、Kotlin、Ceylon、ML、F♯、C ++などの名前が付けられています。Javaでも型推論の形式は限られています。
動的に型付けされたプログラミング言語では、変数には型さえありません。型は実行時に動的にのみ存在し、静的には存在しません。値と式のみが型を持ち、実行時のみ、変数は型を持ちません。
たとえば、ECMAScriptの場合:
const age = 23;
let age = 23;
そして最後に、多くの言語では、変数を宣言する必要さえありません。例:Rubyの場合:
age = 23
実際、最後の例は多くのプログラミング言語で有効です。たとえば、まったく同じコード行がPythonでも機能します。
そう、
auto i = 1 // i is inferred to type intなどvector<int> vec; auto itr = vec.iterator(); // itr is inferred to type vector<int>::iterator。それがどのように機能するかを知りたい場合は、仕様で調べることができます。
自然言語を使用して情報を参照する場合、それはあまり正確ではなく、特に、あなたの意図について他の人にあまり伝えません。自然言語で数学を行おうとすると、同様の問題が発生します。正確性が十分ではありません。
プログラミングは複雑です。エラーが発生するのは非常に簡単です。タイプは、エラー状態を検出することにより、不正なプログラムの状態を防ぐように設計されたチェックシステムの一部です。言語によって型の使用方法が異なります。一部の言語では、コンパイル時にエラーを検出するために型を頻繁に使用します。ほとんどすべての言語には、実行時エラーとして互換性のない型の概念があります。通常、型エラーはプログラムの何らかのバグを示します。エラーが発生してもプログラムの続行を許可すると、非常に悪い答えが返される可能性があります。間違った答えや間違った答えを得るよりも、プログラムを停止することを好みます。
別の言い方をすると、型はプログラムの動作に対する制約を表します。制約は、何らかのメカニズムによって実施される場合、保証を提供します。そのような保証は、プログラムについて考えるのに必要な推論の量を制限し、プログラマーのためにプログラムを読んで維持するタスクを単純化します。型、および型エラーを検出するツール(つまり、コンパイラ)の意味がなければ、プログラミングの負荷はかなり高くなるため、コストがかかります。
(多くの)人間がヨーロッパ、米国、および国際電話番号を簡単に区別するのは事実です。ただし、コンピューターは実際には「考える」ことはなく、言われたらヨーロッパの米国の電話番号をダイヤルします。たとえば、型は、コンピュータに「考える」方法を教える必要なく、これらのケースを区別するための良い方法です。一部の言語では、アメリカの電話システムでヨーロッパの電話番号を混在させようとすると、コンパイル時エラーが発生する場合があります。このエラーは、プログラムを実行する前に、プログラムを変更する必要があることを示しています(おそらく、電話番号を国際ダイヤルシーケンスに変換するか、代わりにヨーロッパの電話番号を使用して)。
さらに、コンピューターが考えないように、フィールドまたは変数の名前(例phonenumber:)は、コンピューターにとっては何の意味もありません。コンピューターにとって、そのフィールド/変数名は単なる「blah123」です。すべての変数が「blahxxx」の場合、プログラムがどのようになるかを考えてください。うわぁ。まあ、それはコンピュータが見るものです。型を提供すると、コンピューターは、その名前だけでは推測できない変数の意味を理解できます。
さらに、@ Robertが言うように、C#のような言語は適切な型を決定する一連のルールである「型推論」を実行するため、多くの現代言語では昔のように型を指定する必要はありませんコンテキスト内の変数。C#は、ローカル変数の型推論のみを提供しますが、仮パラメーター、またはクラスフィールドまたはインスタンスフィールドでは提供しません。
Types are part of a system of checks that ...のOPに直接応答するためWhy do we have to specify data type at all?です。
static member add x y = x + y、member x.Append s = x.Text + s。最初のケースでは、xとyなるように推測されるintため、加算のS。彼らはの種類に応じて有効なものは何でもできるでしょう後者の場合x.Text-それはだ場合string、その後sになるstringだけでなくとして。ただし、型注釈はドキュメントであることに同意します。
他の答えに加えて、含めるべきことが1つあります。コンピューターはほんの一部であることを忘れないでください。バイトを教えてください:
26 3A 00 FF
それはどういう意味ですか?この方法でコンピューターに保存されますが、解釈することなく、ほんの少しです。4つのASCII文字にすることができます。整数にすることもできます。配列内のいくつかのバイトである可能性があります。オブジェクトの一部である可能性があります。それは、その猫のビデオがバッファリングしている場所へのポインタである可能性があります。アセンブリ以降のほとんどすべてのプログラミング言語には、ビットを解釈して意味のある計算を行う方法を知るための何かが必要です。
そして、コンピューターはそれらのビットの意味を知ることができないので、それをあなたに伝える必要があります-タイプ注釈を介して明示的に、または他の回答で言及されたタイプ推論メカニズムを介して暗黙的に。
コンピューターがこの情報を必要とする理由の答えは、データ表現に関係しています。
「データ型」の名前は、コンピューターがコンピューターのメモリに0と1の未加工の状態から情報を格納および取得するのに役立つルールへの参照です。
たとえば、通常の8ビットASCII文字は、コンピューターメモリ(RAMまたはディスク)に01000001(大文字の「A」、ASCIIコード65)または00001000(パーセント記号)、または0とこれらの8ビットの1。
別の例として、いくつかの8ビット符号なし整数は00000101(数字5)または00001000(数字8)として保存されます。
8と%文字のバイナリ表現が同じであることに注意してください。ただし、タイプが異なるため、意味が異なります。
データ型を推測する言語でさえ、「すべての変数の型はプログラマーによって宣言されなければならない」という規則はないかもしれません。各データ型にはさらに多くのルールがあります。
したがって、これらでも0と1の意味を理解するためにデータ型が必要です。たとえば、2つの文字を「追加」しようとすると文字列連結機能を実行でき、2つの整数を追加しようとすると整数加算を実行できます。
では、あなたの話も聞かせてのは、あなたが電話番号をサムを求めなかったと言うが、サムはあなたにそれに書かれた「1123581321」を持っている一枚の紙を与えます。サムが最初の8つのフィボナッチ数のファンなのか、それとも電話番号なのかはわかりません。推測するには、1日前にSamに電話番号を尋ねた、メモに「Call Me」と表示される、または数字を数えて見つけた場合のように、利用可能なコンテキストとキューを考慮する必要があります。ほとんどの電話番号のパターンに一致します。そうして初めて、あなたはそれがあなたが電話をかけることができる電話番号であり、あなたが電卓にパンチするいくつかの数字ではないことを知っているでしょう。
数字が電話番号であるという推測につながったこれらのヒントが、値の型を推測する宣言を必要としないコンピューター言語をヒントが導く方法に似ていることに注意してください。
一部の言語では、データ型を指定する必要はありません。
型推論をサポートする言語は通常、使用法からデータ型を把握できます。例えば、
var name = "Ali"
値は引用符で囲まれているため、内部的に文字列として入力されます。
一部の言語では、変数を宣言する必要もありません。変数は、最初に使用されるときに作成されます。ただし、いくつかの重要な理由から、変数を具体的に宣言することがベストプラクティスと見なされています。主にそうすることはあなたの意図を表現するからです。
var name = "Ali"スタイルは、現代のために実際によくある静的型付け言語。静的に型付けされた言語では、型は作成時に固定されますが、それでも初期化子によって決定できます。動的に型付けされた言語の定義では、型は変数ではなく値に付加されます。したがって、変数に値を割り当てると、変数のタイプも設定されます。
var x = 5; x = "";最初のステートメントでx「Number」タイプが関連付けられるため、次のようなコード(Javascript)が許可されない動的に型付けされた言語はありますxか?動的型付けとの競合の並べ替え。そうでない場合、変数と関連付けられた型は、値との型の関連付けを超えてどのような影響を与えますか?
x = "";の型を以前は数値だった場合でも文字列に変更します。
それが言語設計で指定されているからです。したがって、あなたの質問に答えるには、C#やC ++などの言語での明示的な型指定の背後にある意図を調べる必要があります。(まあ、C#はC ++が行うのでC#が行うので、C#がそれを行うので、当時の意図を確認する必要があります)。
まず、明示的かつ静的な型付けはコーディングの厳密さを提供します-変数を整数に指定すると、変数に文字または文字列を割り当てるときにコンパイラとソフトウェアが驚いてエラーをスローすることを意味します。動的な型指定は、不注意な人の頭痛の種になる可能性があります(配列や空の文字列などの真実性に対するPHPまたはJavaScriptのアプローチを単純に見てください)。
暗黙的な型付けで静的にすることができます-変数を文字列として初期化すると、変数は文字列のみになりますが、これは人間がコードを読む際に問題を引き起こす可能性があるということです)。
また、一部の言語では、この擬似コードのようなものを記述して、文字列入力からクラスを初期化することもできます。
PhoneNumber phoneNumber = "(61) 8 8000 8123";
第二に、明示的な型指定もメモリ割り当てと連動します。int型は、常に非常に多くのバイトです。A のPhoneNumberは、非常に多くのバイトです。コンパイラは、適切なサイズのメモリブロックを割り当てることができます。このメモリブロックは、後で値を割り当てるときに必要なスペースを確認することなく後で使用できます。
PhoneNumber phoneNumber;
...
phoneNumber = "some value from somewhere";
最後に、混乱を取り除きます... 123は整数か符号なし整数ですか?同じバイト数が必要ですが、どちらのタイプの変数に格納される最大値も大きく異なります...
これは、明示的が暗黙的よりも優れていると言っているわけではありませんが、言語設計はこれらの種類の選択に依存しており、C#は暗黙的型付けとは異なる動作をします。PHPとjavascriptは、明示的な入力では異なる動作をします。
サムはコンパイラよりも賢いからです。たとえば、電話番号を教えてくださいと言った場合、最後の4桁のみが必要な勤務先番号であるかどうかに、国のプレフィックスまたは市外局番のどちらを指定するかを指定しません。また、地元のピザジョイントの数を尋ねると、「pizza4u」という答えに対処できます。
サム、文脈からそれを理解します。コンパイラーはコンテキストからそれを把握することもできますが、サムはそれが上手です(そして、プロセスを中断して説明を求めることができます)。
型と変数には2つの基本的なアプローチがあります。変数には型があり、その場合、その型で許可されないアクションは禁止され、コンパイルが妨げられます。タイプは実行時にキャッチされます。
それぞれのアプローチには長所と短所があります。一般に、コンパイラの作成者は、欠点を最小限に抑え、利点を最大限に活用しようとします。これが、たとえばC#var phoneNumber = GetPhoneNumber();がGetPhoneNumberの署名からphoneNumberのタイプを許可し、推論する理由です。つまり、メソッドの型を宣言する必要がありますが、結果を受け取る変数は宣言する必要はありません。一方、javascriptにはさまざまなタイプのヒント/強制プロジェクトがあります。すべてがトレードオフです。
データの保存方法の問題です。サムとのやり取りは、書き出すことができるが、8文字分の紙しか持っていないように求めていれば、より良い比較になるでしょう。
「サム、電話番号を教えて」
「5555555555」
「いや、私は紙切れです。事前にどれだけのデータを要求していたかを事前に知っていれば、もっとよく準備できたはずです!」
その代わり、ほとんどの言語では型を宣言するため、事前に知って準備します。
「サム、電話番号の長さは?」
「10文字。」
「さて、それからもっと大きな紙をもらおう。今すぐphoneNumberをくれ。」
「5555555555」
「ありがとう!サムありがとう!」
データが保存される実際の基本的な方法を見ると、さらに難しくなります。あなたが私のような人なら、雑多なメモ、数字が走り書きされただけで、何の文脈もラベル付けもされていないノートブックがあり、3日後にその意味がわからない。これはコンピューターにとっても何度も問題です。多くの言語には、「int」型(int、long、short、byte)および「float」(float、double)型があります。なぜそれが必要なのですか?
まず、整数がどのように格納され、一般的にコンピューター内で表現されるかを見てみましょう。基本レベルでは、すべてバイナリ(1と0)であることをご存知でしょう。バイナリは実際には、10進数システムとまったく同じように機能する番号システムです。10進数で、0から9(書き込みのない無限の暗黙の先行ゼロを含む)をカウントし、0にロールオーバーして次の桁をインクリメントして10にします。19から20にロールオーバーするまで繰り返します。 99から100にロールオーバーするまで繰り返します。
バイナリも同じです。ただし、0〜9の代わりに0〜1をカウントします。0、1、10、11、100、101、110、111、1000。 1001として。これは実際の数値です。正確にその形式で加算、減算、乗算などを行うことができます。10 + 1 =11。10+ 10 = 100(1から0にロールオーバーして1を運びます)。11 x 10 = 110(および同等に、11 + 11 = 110)。
現在、実際のメモリ(レジスタを含む)には、ビット(潜在的な1'sまたは0 ')のリスト、配列、呼び出したいものがあり、これらのビットを論理的に整理して、問題は、小数で何をしますか?レジスタの2つのビットの間にハードウェアを挿入することはできません。各ビットペアの間に「10進ビット」を追加するとコストがかかりすぎます。じゃあ何をすればいいの?
エンコードします。一般に、CPUまたはソフトウェアのアーキテクチャがこれを行う方法を決定しますが、1つの一般的な方法は、レジスタの最初のビットに仮数(シフトした数字)で符号(+または-、通常1は負)を格納することですただし、次のXのビット数の場合は小数を取り除く必要が何度もあり、残りの場合は指数(シフトする必要がある回数)が必要です。科学表記法に似ています。
入力することで、コンパイラーは何を見ているかを知ることができます。レジスタ1に値1.3を保存したと想像してください。ここでは、符号用に1ビット、仮数用に4ビット、指数用に3ビット(符号用1ビット、大きさ2)の独自の空想エンコーディングスキームを考えます。これは正の数であるため、符号は正(0)です。仮数は13(1101)、指数は-1(101(負の場合は1、01 = 1))になります。したがって、レジスタ1に01101101を格納します。この変数を入力しなかったので、ランタイムがそれを使用するとき、「確かに、これは整数です」と言うので、値を出力するときに109(64 + 32 + 8 + 4 + 1)、これは明らかに正しくありません。
ただし、すべての言語で明示的に入力する必要があるわけではありません。C#には、変数の型をコンパイル時に解釈させるキーワード "var"があり、Javascriptなどの他の言語は完全に動的に型付けされ、変数に整数を格納し、ブール値に割り当てることができます。再度文字列に割り当てると、言語はすべてを追跡します。
しかし、コンパイラー、インタープリター、またはランタイムの方がはるかに簡単です-そして、すべてのタイピングを通してソートする貴重なリソースを費やす必要がないため、多くの場合、プログラムが高速になります-プログラマー、どのようなあなたがそれを与えているデータ。
変数のデータ型を宣言する必要がないプログラミング言語があります。事前に変数を宣言する必要のないプログラミング言語もあります。すぐに使用できます。
変数名を宣言しない場合の問題は、誤って変数名のスペルを間違えた場合、まったく関係のない新しい変数を誤って作成してしまうことです。あなたがプログラムを実行すると、なぜだから、あなたが把握することはできません地獄あなたは突然設定変数ことはそれで何も持っていない、デバッグの多くの時間後に、あなたはのろわ名前間違って入力した実現まで...!GRRR !!
そのため、事前に使用する変数名を宣言する必要があります。そして今、間違った名前を入力すると、コンパイル時エラーが発生します。これは、プログラムが実行される前に、バグの正確な場所をすぐに知らせます。それほど簡単ではないですか?
データ型についても同様です。プログラミング言語の中には、型の種類を宣言する必要がないものがあります。customer顧客オブジェクト全体ではなく、実際には顧客の名前にすぎない変数がある場合、普通の文字列から顧客の住所を取得しようとしてもうまくいきません。静的型付けの全体的なポイントは、プログラムがコンパイルされないことです。それは大声で文句を言い、問題のある正確な場所を指し示します。これは、コードを実行して、なぜコードが機能しないのかを理解しようとするよりもはるかに高速です。
これらはすべて、コンパイラーに何をしようとしていたかを伝えるための機能であるため、実際に何をしたかをチェックし、それが理にかなっていることを確認できます。これにより、コンパイラーが自動的にバグを見つけることができます。これは大したことです。
(遠い昔に、サブルーチンを宣言する必要はありませんでした。GOSUB特定の行番号にしたいだけです。サブルーチン間で情報を受け渡したい場合は、特定のグローバル変数を設定し、サブルーチンを呼び出してから、他の変数時にリターンする。しかし、それは、それが作る驚くほど簡単なパラメータの一つを初期化するために忘れて。だから今、ほぼすべての近代的なプログラミング言語を使用して、我々はあなたがそれらすべてを指定したチェックできるように実際のパラメータサブルーチンは、必要なものを宣言することを求めています。 )
var x=1同様の結果を出すことができます。しかし、それは何もありません。Haskellでは、あなたは全くタイプの署名であなたの全体のプログラムを書くことができ、まだそれは(ない正確に主流けれども。)...すべての静的に型付けされ、あなたがミスをした場合あなたはまだエラーを取得しています
for (auto i=0; i<SomeStdVector.size(); ++i)とリンターは文句を言うでしょう。なぜなら署名された型を推測し、それを符号なしの型と比較するためです。書く必要がありますauto i=0ul(型情報を再度明示的に入力するのでsize_t i=0、最初に書くだけです)。
通常の英語を使用している場合、PhoneNumberを使用するためにintとして宣言する必要はありません。たとえば、友人のサムに電話番号を教えてもらったら、
「サムが電話番号を教えて」
言わないよ>
「Char(20)サムがint phoneNumberをくれた」
データ型を指定する必要があるのはなぜですか?
オーバーポップMathOverflowや理論計算機科学、彼らは誤解の可能性がないことを保証したい場合、人間が互いにalogrithmsを伝え方法のアイデアを得るためにしばらくの間お読みください。または、成熟したプログラミング言語の標準を読んでください。
どのような種類の値を用語に許可するかを定義することは、人間同士であっても非常に正確なコミュニケーションの実践の一部であることがわかります。
あなたが気づいたのは、日常のやり取りはかなり定期的であり、人間はかなりフォールトトレラントなので、電話番号についての誤解は参加者の共通の知識によって一般に回避されます。
しかし、他の国の誰かの電話番号を削除しようとしたことはありますか?彼らは国際アドレッシングに到達するためにゼロをプッシュする回数を明示的に教えましたか?彼らはあなたの国コードを教えましたか?そのように認識しましたか?あなたは何桁を期待していましたか?いくつ取得しましたか?数字をグループ化する方法を知っていましたか?または、グループ化に意味がある場合でも?
突然問題は非常に難しくなり、送信者が意図したとおりに受信した番号が理解されたことを明示的に確認するために、おそらくもっと注意を払ったでしょう。
多くの初期プログラミング言語(特にFortran)では、使用する前に変数を宣言する必要がありませんでした。
これにより、多くの問題が発生しました。本当に明白なことの1つは、コンパイラが単純な印刷上のエラーをほぼ確実にキャッチできなくなったことです。既存の変数を変更することになっているがタイプミスがあるコードがある場合、新しい変数を作成(および値を割り当て)したばかりの完全に正当なコードがまだあります。
longVariableName = 1
// ...
longVaraibleName = longvariableName + anotherLongVariableName
さて、これを単独で見てみると、すでにタイプミスを問題の原因として言及しているので、タイプミスと問題をここで見つけるのはかなり簡単でしょう。これが他の多くのコードの真ん中に埋まっている長いプログラムでは、見逃しがちです。
現在でも多くの動的に型付けされた言語を使用している場合でも、同じ基本的な問題を簡単に取得できます。変数に代入した場合に警告する機能を備えているものもありますが、それを読み取らない(これはヒューリスティックにこのような問題をかなり発見します)両方ともそのようなものを持っていません。
変数を宣言すると、メモリにスペースが割り当てられますが、マシン(この場合はコンピューター)は、その変数に割り当てられるスペースの量をまだ知りません。
例: -あなたはそれ以外のマシンは、それが割り当てなければならないことを自身で判断することはできません、あなたはその番号を格納するデータ型を指定する必要があり、この場合には、入力に任意の数のユーザーを尋ねるプログラムを作成する2バイト または 2ギガバイト、それはしようとすると、一方、プログラムでデータ型を指定した場合、コンパイル後に、マシンは必要に応じて適切なスペースを割り当てます。