web-dev-qa-db-ja.com

宣言型プログラミングと命令型プログラミングの違いは何ですか?

私はウェブを探していて、私にいくらかの光を投げかける宣言型および命令型プログラミングの定義を探していました。しかし、私が見つけたいくつかのリソースで使用されている言語は気が遠くなります - 例えば Wikipedia で。誰かが私に見せるという現実的な例を持っていますか?それはこの主題に何らかの視点をもたらすかもしれません(おそらくC#で)。

459
Brad

宣言型プログラミングと命令型プログラミングの優れた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);
}

ここで、私たちは言っています:

  1. 結果コレクションを作成する
  2. コレクション内の各番号をステップスルーする
  3. 数をチェックし、それが奇数であれば、それを結果に追加してください

一方、宣言的プログラミングでは、欲しいものを記述するコードを書くことができますが、それをどうやって取得するか(必ずしも希望する結果を宣言する必要はありません)ステップバイステップではありません):

var results = collection.Where( num => num % 2 != 0);

ここでは、「コレクションをステップスルーします。奇数の場合は結果コレクションに追加します。」ではなく、「すべてのアイテムを奇妙な場所に渡してください」と言っています。

多くの場合、コードも両方のデザインが混在したものになるため、常に白黒とは限りません。

685
Reed Copsey

宣言的プログラミングはあなたが言うとき what 欲しいものであり、命令型言語はあなたが言うとき how 欲しいものを得るためのものです。

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)

最初の例は宣言的です。リストを構築するための「実装の詳細」を指定しないからです。

C#の例では、LINQを使用すると宣言型のスタイルになります。なぜなら、 how と言っていないからです。 なに ほしいと言っているだけです。 SQLについても同じことが言えます。

宣言型プログラミングの利点の1つは、手作業で作成した場合よりも優れたコードが得られる可能性があることをコンパイラが判断できるようにすることです。次のようなクエリがある場合は、SQLの例で実行します。

SELECT score FROM games WHERE id < 100;

sQLの "コンパイラ"は、このクエリを "最適化"することができます。これは、idがインデックス付きフィールドであることを認識しているか、インデックス化されていないことを意味します。あるいは、SQLエンジンは、これが迅速な並列検索のために8コアすべてを利用するのに最適な時期であることを知っているかもしれません。 あなた は、プログラマーとして、これらの条件のいずれにも関心を持っていません。そして、そのように特別なケースを処理するためにコードを書く必要はありません。

124
Mark Rushakoff

宣言型と命令型

プログラミングパラダイム は、コンピュータプログラミングの基本的なスタイルです。 4つの主なパラダイムがあります:命令型、宣言型、機能型(宣言型パラダイムのサブセットと見なされます)およびオブジェクト指向です。

宣言型プログラミング :制御の流れ(How do)を記述せずに、計算のロジック(what do)を表現するプログラミングパラダイムです。宣言的ドメイン固有言語(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が要求された結果を提供することを信頼しなければなりません。

92
AliKarimi

宣言的/命令的プログラミングの議論でめったにポップアップしない別の例を追加します。

C#では、さまざまなテクノロジを使用してUIを構築できます。

最も重要なことは、DirectXやOpenGLを使ってボタン、チェックボックスなどを非常に命令的に描画することです。ユーザーインターフェイスを描画する方法を言うのはあなた次第です。

宣言の終わりには、WPFがあります。あなたは基本的にXMLを書く(そうそう、「XAML」と技術的に)、そしてフレームワークはあなたのために仕事をする。あなたはユーザーインターフェイスがどのように見えるかを言います。そのやり方を理解するのはシステム次第です。

とにかく、考えるべきもう一つのこと。一方の言語が宣言型または命令型であるからといって、それが他の言語の特定の機能を備えていないとは限りません。

また、宣言型プログラミングの利点の1つは、目的をコードの読み取りから理解しやすくなるのに対して、命令型では実行を細かく制御できることです。

そのすべての要旨:

宣言的 - >やりたいwhat

必須 - > howあなたがやりたいこと

42
Erich Mirabal

上記のすべての回答およびその他のオンライン投稿には、次のことが記載されています。

  • 宣言的プログラミングを使用すると、必要な内容を記述するコードを記述できますが、取得方法は必ずしも必要ではありません
  • 命令型プログラミングよりも宣言型プログラミングを好むべきです

彼らが私たちに言わなかったことは、それを達成する方法です。プログラムの一部をより宣言的にするには、他の部分が抽象化を提供するで実装の詳細(命令的コード)を非表示にする必要があります。

  • たとえば、LINQはループ(for、whileなど)よりも宣言的です。たとえば、list.Where()を使用して、新しいフィルター処理されたリストを取得できます。これが機能するために、Microsoftは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();
42
engineforce

私はケンブリッジコースからの説明とその例を気に入っていました。

  • 宣言 - 指定する=whatnot howそれを行うには
    • 例:HTMLはWebページに表示される内容を記述しています。画面上に描画する方法は記述していません。
  • 必須 - whathow[の両方を指定]
    • int x; - what(宣言型)
    • x=x+1; - どうやって
23

命令型プログラミングでは、開発者はコードの実行方法を段階的に定義する必要があります。命令的な方法で指示を出すには、「1st Streetに行き、Mainに左折し、2ブロックドライブし、Mapleに右折し、左側の3番目の家に立ち寄ってください」と言います。 :「スーの家に運転しなさい。」ある人は何かをする方法を言います。もう一方は何をする必要があるかを言います。

宣言型には、命令型に比べて2つの利点があります。

  • それは旅行者に一連の指示を暗記することを強制するものではありません。
  • それは旅行者が可能な限りルートを最適化することを可能にします。

カルバート、Cクルカルニ、D(2009)。必須のLINQアディソンウェズリー。 48。

22
GorkemHalulu

違いは主に抽象化の全体的なレベルに関係しています。宣言的で、ある時点で、あなたはプログラムがあなたの結果を得る方法に関して多くの自由度を持つように個々のステップから遠く離れています。


あなたは連続のどこかに落ちているようにすべての命令を見ることができました:

抽象度:

Declarative <<=====|==================>> Imperative

宣言的な実世界の例:

  1. 司書、モービーディックのコピーをチェックしてください。 (司書、彼らの裁量で要求を実行するための最良の方法を選択します)

命令的な実世界の例:

  1. 図書館に行く
  2. 本の整理システムを探す(カードカタログ - オールドスクール)
  3. カードカタログの使い方の研究(あなたも忘れてたよ、右)
  4. 棚がどのようにラベル付けされ整理されているかを理解する。
  5. 本がどのように棚の上に配置されているかを理解する。
  6. 上記の本を見つけるための組織システムとのカードカタログからの相互参照本の場所。
  7. チェックアウトシステムに本を持って行きなさい。
  8. 本をチェックしてください。
16
Lucent Fox

命令型プログラミングは、順序などの指定のように、何をすべきか、またそれをどのように行うかをコンピュータに明示的に指示することです

C#:

for (int i = 0; i < 10; i++)
{
    System.Console.WriteLine("Hello World!");
}

宣言とは、コンピュータに何をすべきかを指示するときですが、実際にはその方法を指示しません。 Datalog/Prologはこの点に関して頭に浮かぶ最初の言語です。基本的にすべて宣言的です。あなたは本当に注文を保証することはできません。

C#ははるかに命令型のプログラミング言語ですが、Linqのように特定のC#機能はより宣言的です。

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からの例)

10
McKay

コンピュータサイエンスでは、宣言型プログラミングは制御フローを記述せずに計算の論理を表現するプログラミングパラダイムです。

Http://en.wikipedia.org/wiki/Declarative_programmingから

一言で言えば、宣言型言語は、制御フロー(ループ、ifステートメントなど)の複雑さがないため、より単純です。

良い比較は、ASP.Netの「分離コード」モデルです。宣言型の「.ASPX」ファイルがあり、次に必須の「ASPX.CS」コードファイルがあります。私は、スクリプトの宣言的な半分で必要なことをすべて実行できれば、実行されていることをもっと多くの人がフォローできるということをよく感じます。

8
kervin

Philip Robertsから盗んだ ここ

  • 命令型プログラミングはマシンに何かをする方法を伝えます(結果としてあなたがしたいことが起こります)
  • 宣言型プログラミングは、あなたが何をしたいのかをマシンに伝えます(そして、コンピュータはそれをどうやって行うかを見つけ出します)。

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です。

4
Premraj

C#の宣言型プログラミングツールとしてAttributeクラスについて言及していないのはなぜだろう。このページの一般的な答えは、宣言型プログラミングツールとしてのLINQについて話したところです。

ウィキペディアによると

一般的な宣言型言語は、データベースクエリ言語(例えば、SQL、XQuery)、正規表現、論理プログラミング、関数型プログラミング、および構成管理システムのものを含む。

そのため、機能的な構文としてのLINQは宣言型メソッドですが、構成ツールとしてのC#のAttributeクラスも宣言型メソッドです。これについてもっと読むための良い出発点は次のとおりです。 C#属性プログラミングの概要

2

宣言型プログラムは、多少なりとも「普遍的な」命令型実装の単なるデータです。

pluses:ハードコードされた(そしてチェックされた)フォーマットでデータだけを指定することは、必須のアルゴリズムの変形を直接指定するよりも簡単でエラーが少ないです。複雑な仕様の中には直接書くことができないものもあり、DSL形式でしか書けないものもあります。 DSLのデータ構造で最もよく使われるのは、セットとテーブルです。要素/行の間に依存関係がないからです。そしてあなたが依存関係を持っていないとき、あなたは変更する自由とサポートの容易さを持っています。 (例えばモジュールとクラス - あなたが幸せなモジュールとあなたが壊れやすい基本クラスの問題を抱えているクラスとを比較してください)宣言性とDSLのすべての商品はそのデータ構造(テーブルとセット)の利点からすぐに得られます。 DSLが多かれ少なかれ抽象的(うまく設計されている)であれば、宣言型言語vmの実装を変更することができます。たとえば、並列実装を行います。あるいは、他のOSなどに移植すること。すべての優れた仕様のモジュール式分離インターフェースまたはプロトコルによって、サポートの自由度と容易さが向上します。

マイナス:あなたは正しいと思います。一般的な(そしてDSLによってパラメータ化された)命令型アルゴリズム/ vmの実装は、特定のものより遅く、そして/またはメモリを消費する可能性があります。ある場合には。そのようなケースがまれな場合 - それを忘れて、遅くしましょう。それが頻繁なら - あなたはいつでもあなたのDSL/vmをその場合に拡張することができます。どこか他のすべてのケースを遅くして、確かに...

P.SフレームワークはDSLと命令の中間にあります。そして、すべての中途半端な解決策として…彼らは、利益ではなく欠点を兼ね備えています。彼らはそれほど安全でも速くもない:)何でも屋敷のhaskellを見てください - それは強力な単純なMLと柔軟なメタプロッグPrologの間の中間点です...そしてそれはなんとモンスターです。 Prologはブール値だけの関数/述語を持つHas​​kellとして見ることができます。そしてその柔軟性がHaskellに対してどれほど単純であるか...

2
4KCheshireCat

モバイルアプリ開発に関して別の例を追加するだけです。 iOSとAndroidにはInterface Buildersがあり、そこでアプリのUIを定義できます。

これらのBuilderを使用して描画されたUIは本質的に宣言型であり、そこでコンポーネントをドラッグアンドドロップします。実際の排水は、フレームワークとシステムによって発生し、実行されます。

しかし、コンポーネント全体をコードで描画することもできます。それは本質的に必須です。

また、Angular JSのような新しい言語の中には、宣言的にUIを設計することに焦点を当てているものがあり、他の多くの言語でも同じサポートが提供されています。 JavaのようにネイティブデスクトップアプリケーションをJava SwingまたはJava FXで描画するための宣言的な方法はありませんが、近い将来には可能になります。

2
Puneet Sharma

私の理解では、どちらの用語も哲学に根ざしており、宣言型と必須型の知識があります。宣言的知識は真理の表明、数学公理のような事実の表明です。それはあなたに何かを伝えます。命令型、または手続き型の知識は、何かに到達する方法を段階的に説明します。それがアルゴリズムの定義が本質的にしていることです。もしそうなら、コンピュータプログラミング言語と英語を比較してください。宣言文は何かを述べます。退屈な例ですが、2つの数値が等しいかどうかをJavaで表示する宣言的な方法は次のとおりです。

public static void main(String[] args)
{
    System.out.print("4 = 4.");
}

一方、英語の命令文は命令を出すか、ある種の要求を出します。そのため、命令型プログラミングは単なるコマンドのリストです(これを実行してください)。これは、ユーザー入力を受け付けるときに2つの数値が等しいかどうかをJavaで表示するための必須の方法です。

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);
}

基本的に、宣言型知識は特定の要素をスキップしてそれらの要素を抽象化する層を形成します。宣言型プログラミングも同じです。

1
Matthew Conrad