私は私にいくつかの光を当てるであろう宣言的および命令的プログラミングの定義を探してウェブを検索してきました。しかし、私が見つけたいくつかのリソースで使用されている言語は、たとえばWikipediaで、気が遠くなるようなものです。誰かがこのテーマに何らかの視点をもたらすかもしれない実際の例を(C#で)持っている人はいますか?
私は私にいくつかの光を当てるであろう宣言的および命令的プログラミングの定義を探してウェブを検索してきました。しかし、私が見つけたいくつかのリソースで使用されている言語は、たとえばWikipediaで、気が遠くなるようなものです。誰かがこのテーマに何らかの視点をもたらすかもしれない実際の例を(C#で)持っている人はいますか?
回答:
宣言型プログラミングと命令型プログラミングの優れたC#の例は、LINQです。
で不可欠なプログラミング、あなたは、段階的に起こるようにしたいものをコンパイラに伝えます。
たとえば、このコレクションから始めて、奇数を選択します。
List<int> collection = new List<int> { 1, 2, 3, 4, 5 };
命令型プログラミングでは、これをステップ実行して、必要なものを決定します。
List<int> results = new List<int>();
foreach(var num in collection)
{
if (num % 2 != 0)
results.Add(num);
}
ここで、私たちは言っています:
宣言型プログラミング、他の一方で、あなたがしたいが、何を記述したコードを書く必要はない、それを取得する方法(ご希望の結果を宣言し、ではなく、ステップバイステップ):
var results = collection.Where( num => num % 2 != 0);
ここでは、「コレクションをステップスルーします。このアイテムを確認してください。奇妙な場合は、結果のコレクションに追加してください。」ではなく、「奇妙な場所にすべてのものを与える」と言います。
多くの場合、コードも両方のデザインが混在しているため、常に白黒であるとは限りません。
collection.Where
はLinqが提供する宣言構文を使用していません- 例としてmsdn.microsoft.com/en-us/library/bb397906.aspxを参照してくださいfrom item in collection where item%2 != 0 select item
。宣言形式になります。関数がSystem.Linq名前空間にあるからといって、関数を呼び出しても宣言型プログラミングにはなりません。
宣言型プログラミングはあなたが欲しいものを言うときであり、命令型言語はあなたが欲しいものを得る方法を言うときです。
Pythonの簡単な例:
# Declarative
small_nums = [x for x in range(20) if x < 5]
# Imperative
small_nums = []
for i in range(20):
if i < 5:
small_nums.append(i)
最初の例は宣言型です。これは、リストの作成に関する「実装の詳細」を指定していないためです。
あなたが言っていないので、宣言型スタイルでLINQの結果を使用して、一般的に、C#の例に結びつけるために、どのようにあなたが欲しいものを得ること。あなたはあなたが欲しいものを言っているだけです。SQLについても同じことが言えます。
宣言型プログラミングの利点の1つは、手動で行うよりも優れたコードになる可能性のある決定をコンパイラが行うことができることです。次のようなクエリがある場合、SQLの例で実行します。
SELECT score FROM games WHERE id < 100;
SQLの「コンパイラ」id
は、インデックス付きフィールドであることを知っているため、このクエリを「最適化」できます。あるいは、インデックス付けされていない可能性があります。この場合、データセット全体を反復処理する必要があります。あるいは、SQLエンジンは、これが8つのコアすべてを高速な並列検索に利用する絶好の機会であることを知っています。 プログラマとして、あなたはそれらの条件のいずれにも関係がなく、そのように特別なケースを処理するためにコードを書く必要はありません。
filter(lambda x: x < 5, range(20))
、これは、短い表記にリファクタリングするもう1つの方法です。これは、より簡潔な表記を作成することを明示的に意図して作成された(pep 202を参照)リスト内包表記(明確な「マップ」セクションと「フィルター」セクションを含む)と違いはありません。そしてこの場合、このリストの理解はより明確/慣用的です。
宣言型と命令型
プログラミングパラダイムは、コンピュータプログラミングの基本的なスタイルです。4つの主要なパラダイムがあります。命令型、宣言型、機能型(宣言型パラダイムのサブセットと見なされます)、オブジェクト指向です。
宣言型プログラミング:制御フロー(方法)を記述せずに、計算のロジック(動作)を表現するプログラミングパラダイムです。宣言型ドメイン固有言語(DSL)のよく知られた例には、CSS、正規表現、SQLのサブセット(SELECTクエリなど)が含まれます。HTML、MXML、XAML、XSLTなどの多くのマークアップ言語は、多くの場合宣言型です。宣言型プログラミングは、一連の命令としてのプログラムと、目的の回答についてのアサーションとしてのプログラムの違いを曖昧にしようとします。
命令型プログラミング:プログラムの状態を変更するステートメントの観点から計算を説明するプログラミングパラダイムです。宣言型プログラムは、プログラミングコマンドまたは数学的表明として二重に見ることができます。
関数型プログラミング:計算を数学関数の評価として扱い、状態や可変データを回避するプログラミングパラダイムです。状態の変化を強調する命令型プログラミングスタイルとは対照的に、関数の適用を強調します。Haskellなどの純粋な関数型言語では、すべての関数に副作用はなく、状態の変化は状態を変換する関数としてのみ表されます。
次のMSDNの命令型プログラミングの例では、1〜10の数値をループして、偶数を見つけます。
var numbersOneThroughTen = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//With imperative programming, we'd step through this, and decide what we want:
var evenNumbers = new List<int>();
foreach (var number in numbersOneThroughTen)
{ if (number % 2 == 0)
{
evenNumbers.Add(number);
}
}
//The following code uses declarative programming to accomplish the same thing.
// Here, we're saying "Give us everything where it's odd"
var evenNumbers = numbersOneThroughTen.Select(number => number % 2 == 0);
どちらの例でも同じ結果が得られ、一方が他方よりも良くも悪くもありません。最初の例ではより多くのコードが必要ですが、コードはテスト可能であり、命令型アプローチにより実装の詳細を完全に制御できます。2番目の例では、コードが間違いなく読みやすくなっています。ただし、LINQでは、舞台裏で行われる処理を制御できません。LINQが要求された結果を提供することを信頼する必要があります。
上記のすべての回答と他のオンライン投稿では、次のことに言及しています。
彼らが私たちに言っていないことは、それを達成する方法です。プログラムの一部をより宣言的にするには、他の部分が抽象化を提供して、実装の詳細(命令コード)を隠す必要があります。
list.Where()
新しいフィルターされたリストを取得するために使用できます。これを機能させるために、マイクロソフトはLINQ抽象化の背後にあるすべての重労働を実行しました。実際、関数型プログラミングと関数型ライブラリがより宣言的である理由の1つは、ループを抽象化して作成をリスト化し、実装の詳細(ループのある可能性が最も高い命令コード)を裏で隠しているためです。
どのプログラムでも、命令コードと宣言コードの両方が常にあります。目指すべきことは、プログラムの他の部分がそれらを宣言的に使用できるように、抽象化の背後にすべての命令コードを隠すことです。
最後に、関数型プログラミングとLINQはプログラムをより宣言的にすることができますが、より多くの抽象化を提供することにより、いつでもより宣言的にすることができます。例えば:
// JavaScript example
// Least declarative
const bestProducts = [];
for(let i = 0; i < products.length; i++) {
let product = products[i];
if (product.rating >= 5 && product.price < 100) {
bestProducts.push(product);
}
}
// More declarative
const bestProducts = products.filter(function(product) {
return product.rating >= 5 && product.price < 100;
});
// Most declarative, implementation details are hidden in a function
const bestProducts = getBestProducts();
PS宣言型プログラミングの極端な例は、新しいドメイン固有言語(DSL)を発明することです。
debit
、deposit
代わりにimparativeコードを繰り返すのなどを、account.balance += depositAmount
宣言型/命令型プログラミングの議論でめったにポップアップしない別の例を追加します。それはユーザーインターフェイスです。
C#では、さまざまなテクノロジーを使用してUIを構築できます。
命令型の最後では、DirectXまたはOpenGLを使用して、ボタン、チェックボックスなどを命令型で行ごと(または実際には三角形ごと)に描画できます。ユーザーインターフェースの描き方はあなた次第です。
宣言の最後には、WPFがあります。基本的にXMLを作成し(技術的には「XAML」)、フレームワークが機能します。あなたはユーザーインターフェースがどのように見えるかを言います。それを行う方法を理解するのはシステム次第です。
とにかく、もう1つ考えるべきことです。1つの言語が宣言的または命令的であるからといって、他の言語の特定の機能がないことを意味するわけではありません。
また、宣言型プログラミングの利点の1つは、コードを読み取ることで目的が通常より簡単に理解されるのに対し、命令型は実行をより細かく制御できることです。
そのすべての要点:
宣言-> what
やりたい
命令型-> how
あなたはそれをやりたい
私はケンブリッジコースの説明とその例が好きでした:
int x;
-何(宣言)x=x+1;
- どうやってCSS
が命令的であることを意味するのでしょうか?
違いは、主に抽象化の全体的なレベルに関係しています。宣言型を使用すると、ある時点で、個々のステップから離れすぎて、プログラムが結果を取得する方法に関して多くの自由度を持つようになります。
すべての命令は、連続体のどこかに落ちていると見ることができます。
抽象度:
Declarative <<=====|==================>> Imperative
宣言的な実世界の例:
命令型の実世界の例:
命令型プログラミングでは、コードの実行方法を段階的に定義する必要があります。命令的な方法で方向を示すには、「1st Streetに行き、Mainで左折し、2ブロック進み、Mapleで右折して、左側の3番目の家に立ち寄ります」と言います。宣言型バージョンは、「ドライブのスーの家」のように聞こえるかもしれません。人は何かをする方法を言います。もう1つは、何を行う必要があるかを示しています。
宣言型スタイルには、命令型スタイルに比べて2つの利点があります。
- 旅行者に長い一連の指示を暗記するように強制するものではありません。
- これにより、旅行者は可能な限りルートを最適化できます。
Calvert、C Kulkarni、D(2009)。必須のLINQ。Addison Wesley。48。
命令型プログラミングは、順序を指定するなど、何をすべきか、どのように行うかをコンピュータに明示的に指示します
C#:
for (int i = 0; i < 10; i++)
{
System.Console.WriteLine("Hello World!");
}
宣言型とは、コンピュータに何をすべきかを指示するときですが、実際にそれを行う方法ではありません。Datalog / Prologは、この点で頭に浮かぶ最初の言語です。基本的にすべてが宣言型です。あなたは本当に注文を保証することはできません。
C#ははるかに命令的なプログラミング言語ですが、特定のC#機能はLinqのようにより宣言的です
dynamic foo = from c in someCollection
let x = someValue * 2
where c.SomeProperty < x
select new {c.SomeProperty, c.OtherProperty};
同じことを命令的に書くことができます:
dynamic foo = SomeCollection.Where
(
c => c.SomeProperty < (SomeValue * 2)
)
.Select
(
c => new {c.SomeProperty, c.OtherProperty}
)
(ウィキペディアLinqの例)
コンピュータサイエンスでは、宣言型プログラミングは、制御フローを記述せずに計算のロジックを表現するプログラミングパラダイムです。
http://en.wikipedia.org/wiki/Declarative_programmingから
簡単に言えば、宣言型言語は、制御フロー(ループ、ifステートメントなど)の複雑さに欠けるため、よりシンプルです。
良い比較は、ASP.Netの「コードビハインド」モデルです。宣言的な「.ASPX」ファイルと、命令的な「ASPX.CS」コードファイルがあります。スクリプトの宣言的な半分で必要なことをすべて実行できれば、より多くの人が実行中の内容を追跡できることがよくあります。
ここでフィリップロバーツから盗む:
2つの例:
1.配列内のすべての数値を2倍にする
命令的に:
var numbers = [1,2,3,4,5]
var doubled = []
for(var i = 0; i < numbers.length; i++) {
var newNumber = numbers[i] * 2
doubled.push(newNumber)
}
console.log(doubled) //=> [2,4,6,8,10]
宣言的に:
var numbers = [1,2,3,4,5]
var doubled = numbers.map(function(n) {
return n * 2
})
console.log(doubled) //=> [2,4,6,8,10]
2.リスト内のすべてのアイテムを合計する
命令的に
var numbers = [1,2,3,4,5]
var total = 0
for(var i = 0; i < numbers.length; i++) {
total += numbers[i]
}
console.log(total) //=> 15
宣言的に
var numbers = [1,2,3,4,5]
var total = numbers.reduce(function(sum, n) {
return sum + n
});
console.log(total) //=> 15
命令型の例では、新しい変数を作成し、それを変更して、その新しい値を返す(つまり、発生させる方法)ことに注意してください。一方、宣言型の例は、特定の入力で実行され、初期入力に基づいて新しい値を返します(つまり、 、何が起こりたいのか)。
命令型プログラミング
C / C ++、Java、COBOL、FORTRAN、Perl、JavaScriptなどのプログラミング規則を必要とするプログラミング言語。そのような言語で書くプログラマーは、データ処理とプログラミングの知識に基づいて、問題を解決するための適切なアクションの順序を開発する必要があります。
宣言型プログラミング
従来のプログラミングロジックを記述する必要のないコンピューター言語。ユーザーは、C ++やJavaなどの手続き型プログラミング言語で必要なプログラムステップではなく、入力と出力の定義に集中します。
宣言型プログラミングの例は、CSS、HTML、XML、XSLT、RegXです。
宣言型プログラムは、多かれ少なかれ「普遍的な」命令型実装/ vmの単なるデータです。
プラス:一部のハードコードされた(およびチェックされた)形式でデータのみを指定することは、いくつかの命令型アルゴリズムのバリアントを直接指定するよりも簡単で、エラーが発生しにくくなります。複雑な仕様の中には、DSL形式でのみ直接記述できないものもあります。DSLのデータ構造で使用されるbestおよびfreqは、セットとテーブルです。要素/行間に依存関係がないためです。依存関係がない場合は、変更の自由とサポートの容易さがあります。(例のモジュールとクラスを比較-満足できるモジュールと脆弱な基本クラスの問題があるクラス)宣言性とDSLのすべての商品は、そのデータ構造(テーブルとセット)の利点からすぐに続きます。別のプラス-DSLが多かれ少なかれ抽象的である(うまく設計されている)場合は、宣言型言語vmの実装を変更できます。たとえば、並列実装を行います。
マイナス:あなたは正しいと思います。一般的な(DSLによってパラメーター化された)命令型のアルゴリズム/ vmの実装は、特定のアルゴリズムよりも低速であるか、メモリを大量に消費している可能性があります。ある場合には。そのようなケースがまれな場合は、忘れてください。ゆっくりしてください。頻度が高い場合は、DSL / vmをいつでも拡張できます。どこか他のすべてのケースが遅くなります、確かに...
PSフレームワークはDSLと命令型の中間にあります。そしてすべての中間的な解決策と同様に...それらは利点ではなく欠陥を組み合わせます。彼らはそれほど安全ではなく、それほど速くありません:)すべてのトレードのジャックhaskellを見てください-それは強力なシンプルなMLと柔軟なメタプログラムPrologの中間であり、それはなんと怪物でしょう。ブール値のみの関数/述語を持つHaskellとしてPrologを見ることができます。そしてその柔軟性がHaskellに対してどれほど単純か...
C#の宣言型プログラミングツールとしてAttributeクラスについて誰も言及していないのはなぜでしょうか。このページの人気のある答えは、宣言型プログラミングツールとしてのLINQについての話です。
ウィキペディアによると
一般的な宣言型言語には、データベースクエリ言語(SQL、XQueryなど)、正規表現、論理プログラミング、関数型プログラミング、構成管理システムなどがあります。
そのため、関数構文としてのLINQは間違いなく宣言型メソッドですが、構成ツールとしてのC#の属性クラスも宣言型メソッドです。詳細については、次の記事が参考になります。C#属性プログラミングの概要
モバイルアプリの開発に関する別の例を追加するだけです。iOSとAndroidには、アプリのUIを定義できるインターフェイスビルダーがあります。
これらのビルダーを使用して描画されるUIは本質的に宣言型であり、コンポーネントをドラッグアンドドロップします。実際の描画はフレームワークとシステムの下で実行されます。
しかし、コンポーネント全体をコードで描画することもできますが、それは本質的に必須です。
また、Angular JSのようないくつかの新しい言語は、宣言的にUIを設計することに重点を置いており、同じサポートを提供する他の多くの言語を目にする可能性があります。JavaにはJavaスイングまたはJava FXでネイティブデスクトップアプリを描画するための優れた宣言的な方法がないのと同様に、近い将来、そうなる可能性があります。
私の理解では、どちらの用語も哲学にルーツがあり、宣言型と命令型の知識があります。宣言的知識は、真理の主張、数学の公理のような事実の表明です。それは何かを教えてくれます。命令的、または手続き的知識は、何かに到達する方法を段階的に説明します。それがアルゴリズムの定義です。もしそうなら、コンピュータプログラミング言語を英語と比較してください。宣言文は何かを述べています。退屈な例ですが、Javaで2つの数値が互いに等しいかどうかを表示する宣言的な方法を次に示します。
public static void main(String[] args)
{
System.out.print("4 = 4.");
}
一方、英語の命令文は、命令を出すか、何らかの要求をします。したがって、命令型プログラミングは単なるコマンドのリストです(これを実行してください)。Javaでユーザー入力を受け入れている間に2つの数値が互いに等しいかどうかを表示する必須の方法を次に示します。
private static Scanner input;
public static void main(String[] args)
{
input = new Scanner(System.in);
System.out.println();
System.out.print("Enter an integer value for x: ");
int x = input.nextInt();
System.out.print("Enter an integer value for y: ");
int y = input.nextInt();
System.out.println();
System.out.printf("%d == %d? %s\n", x, y, x == y);
}
基本的に、宣言的知識は特定の要素をスキップして、それらの要素に対する抽象化の層を形成します。宣言型プログラミングも同じです。