命令型プログラミングと宣言型プログラミングの違いを知るのは非常に紛らわしいですが、実際の用語で両方の違いを説明できる人はいますか?
Cが命令型言語か宣言型言語かを明確にしてください。
命令型プログラミングと宣言型プログラミングの違いを知るのは非常に紛らわしいですが、実際の用語で両方の違いを説明できる人はいますか?
Cが命令型言語か宣言型言語かを明確にしてください。
警告
一般論が多いので、ご容赦ください。
理論的には
C はimperativeです。コードは何かを行う方法のレシピのように読めるためです。ただし、ポリモーフィズムのために適切な名前の関数と関数ポインターを多数使用すると、C コードを宣言型言語のように見せることができます。
命令型言語では、アルゴリズム/実装に集中します。プロセスの効率性に焦点を当てているため、エンジニアリングは本質的に不可欠です。つまり、何かを実行するために必要な時間やお金 (または CS のメモリ) のコストです。
対照的に、数学は一般的に宣言型です (ただし、証明を書くことはより命令型になる傾向があります)。数学では、答えをどれだけ早く得られるかよりも、正確さと不変の関係/操作の定義に関心があります。
多くの関数型言語は本質的に宣言型である傾向があることに注意してください (R、Lisp など)。
z = x + y とはどういう意味ですか? (セマンティクス)
命令型言語では、メモリ ロケーション x と y から読み取り、それらの値を加算し、結果をメモリ ロケーション z に入れ、すぐに実行することを意味します。x に別の値を割り当てた場合は、z = x + y
ステートメントを再度使用して z を再計算する必要があります。
宣言型(怠惰な) 言語では、z が他の 2 つの変数 x と y の値の合計である変数であることを意味します。z の値を読み取ろうとするまで、加算演算は実行されません。その意味は何ですか?z から読み取る場合、値は常にその時点での x と y の合計になります。ステートメントを再発行する必要はありません。変数がない純粋な宣言型言語では、再発行は実際にはエラーとしてキャッチされます!!!
この例を念頭に置くと、数学者が宣言型言語を好む傾向がある理由がわかります。たとえば、hypotenuse = sqrt( height^2 + length^2 ) を定義でき、そのステートメントを再発行する心配はありません。この関係は、数学の真理が常に成り立つように、常に成り立つ不変式です。
実生活で (そして、なぜ私は気にする必要があるのですか?)
宣言型言語の支持者は次のように主張しています: 間違った (バグのある) 効率的な解決策は役に立たない. 彼らは、変更せずに再利用できる、副作用のない、バグのない状態のない関数を望んでいます。
命令型言語の支持者は次のように主張しています。彼らは、メモリと速度のトレードオフを制御したいと考えています。彼らは、物理的および時間的な制約に基づいて最適化できることを望んでいます。
もちろん、100% 命令的または宣言的なものはありません。 正しく適切に記述された命令型コードは、特定の関係を暗示します。宣言型コードであるOTOH は、十分に深く、言語仕様と組み合わせて、コンパイラ/インタープリターがコードを一連の CPU 命令に変換するのに十分なほど、これらの関係を記述します。
私たちはコンピューターを扱っているため、宣言型のコンパイラー/インタープリターは、時間とメモリのトレードオフを行うのに十分なほどスマートでなければなりませんが、命令型言語では、これらの決定をより明示的に行うのはプログラマー次第です。
したがって、宣言型言語では、プログラマーは変数と他の不変条件の間の関係を定義することに集中する必要があります。これらの関係を CPU の一連の命令/操作に変換するのは、コンパイラ/インタプリタ次第です。ほとんどの宣言型コンパイラ/インタープリターは、現実世界のほとんどのケースを処理するのに十分スマートですが、特殊なケースでは問題が発生する可能性があります。残念ながら、そのような状況では、コンパイラ/インタプリタを説得する必要があります。
どちらの方がよいですか?
宣言型言語の支持者は、そのような言語を使用すると、プログラマーはドメインに集中でき、非プログラマーにとって読みやすいコードを記述できると主張しています。正しいコードを書く方が簡単だ、と提唱者は主張します。ただし、トレードオフは、コンパイラ/インタープリターが正しいメモリと速度のトレードオフを行うように説得するには、言語に関する複雑な知識が必要になる可能性があることです。R、SQL、LISP などの宣言型言語を使用すると、この問題を理解できます。コンピューターとは関係のない新しい宣言型言語を定義することは確かに可能です (ただし、そうすることは、インタープリター/コンパイラーの作成者にとって困難になる可能性があります)。多くの数学者や純粋な CS 研究者は、宣言型言語を好みます。
命令型言語は、マシンをよりきめ細かく制御できる傾向があります。あなたがコンピューターをプログラミングしていることに疑いの余地はありません。落とし穴は、コードのメンテナンスと可読性を損なう不必要な速度の最適化に時期尚早に集中してしまう可能性があることです。速度やメモリが大幅に制限されていた初期のコンピューティングでは、状況に合わせて適切に最適化された、有用な作業を行うための命令型言語が必要でした。エンジニアやいじくり屋は、命令型言語に引き寄せられる傾向があります。
C 言語のいくつかの側面は、明示的な規則がない場合、宣言型になるとコメントしたいと思います...
int i = 4;
int j = 5;
float f = i/j;
float を .80 にするつもりであることを意味しているように思われます (そして、宣言型言語ではそうなる可能性が最も高いです)...しかし、明確に定義されたプロシージャがあるため、 int/int は整数除算を使用して int に評価されます (C ではこれはフロア分割)。
C を命令型にするのは、明示的に定義された動作の側面です。
プログラムの出力を変更しないという保証がある限り、最適化を行うことができるCのレイヤーの下に秘密があり、コンパイラーに宣言的な動作を持たせます。宣言は入力Cプログラムの動作です、しかし最終結果は機能的にそのCプログラムに一致するものになる可能性があります
§5.1.2.3 パート 10:
あるいは、実装は、翻訳単位の境界を越えて関数呼び出しを行う場合にのみ、実際のセマンティクスが抽象セマンティクスと一致するように、各翻訳単位内でさまざまな最適化を実行する場合があります。このような実装では、呼び出し元の関数と呼び出された関数が異なる翻訳単位にある各関数のエントリと関数の戻り時に、外部にリンクされたすべてのオブジェクトの値と、その中のポインターを介してアクセス可能なすべてのオブジェクトの値が抽象セマンティクスに一致します。 . さらに、そのような各関数エントリの時点で、呼び出された関数のパラメータの値と、その関数内のポインタを介してアクセス可能なすべてのオブジェクトの値は、抽象セマンティクスと一致します。このタイプの実装では、
次の部分の具体的な例:
例 2 フラグメントの実行時
char c1, c2; /* ... */
c1 = c1 + c2;
「整数昇格」では、抽象マシンが各変数の値を int サイズに昇格してから、2 つの int を加算して合計を切り捨てる必要があります。2 つの文字の加算がオーバーフローなしで実行できる場合、またはオーバーフロー ラッピングをサイレントに使用して正しい結果を生成できる場合、実際の実行では同じ結果が生成されるだけでよく、プロモーションが省略される可能性があります。
-> 命令型プログラミング: 「マシン」に何かを実行する方法を伝え、その結果、実行したいことが実行されます。
-> 宣言型プログラミング: 「マシン」に何をしたいかを伝え、コンピューターにそれを実行する方法を理解させます。
したがって、C は命令型言語であると言えます。