В чем разница между декларативным и императивным программированием? [закрытый]

Я искал в интернете определение декларативного и императивного программирования, которое пролило бы свет на меня. Однако язык, используемый в некоторых ресурсах, которые я нашел, является сложным - например, в Википедия. Есть ли у кого-нибудь реальный пример, который они могли бы показать мне, что может принести некоторую перспективу этому вопросу (возможно, в C#)?

16 ответов


отличным примером декларативного и императивного программирования на 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);

здесь мы говорим: "Дайте нам все, где это странно", а не " шаг через коллекцию. Проверять этот элемент, если он нечетный, добавьте его в коллекцию результатов."

во многих случаях код будет смесью обоих конструкций, поэтому он не всегда черно-белый.


декларативное Программирование, когда вы говорите что вы хотите, и императивный язык, когда вы говорите как чтобы получить то, что вы хотите.

простой пример в 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 приводит к декларативному стилю, потому что вы не говорите как получить чего вы хотите; вы только говорите что вы хотите. То же самое можно сказать и о SQL.

одним из преимуществ декларативного программирования является то, что оно позволяет компилятору принимать решения, которые могут привести к лучшему коду, чем то, что вы можете сделать вручную. Запуск с примером SQL, если у вас был запрос типа

SELECT score FROM games WHERE id < 100;

SQL "компилятор" может "оптимизировать" этот запрос, потому что он знает, что id является индексированным полем - или, возможно, оно не индексируется, и в этом случае оно в любом случае придется перебирать весь набор данных. Или, может быть, SQL engine знает, что это идеальное время для использования всех 8 ядер для быстрого параллельного поиска. вы, как программист, не связаны ни с одним из этих условий, и вам не нужно писать свой код для обработки любого специального случая таким образом.


декларативного и императивного

на парадигмы программирования - это фундаментальный стиль программирования. Существует четыре основных парадигмы: императивная, декларативная, функциональная (которая считается подмножеством декларативной парадигмы) и объектно-ориентированная.

декларативное Программирование : парадигма программирования, которая выражает логику вычисления (что делать) без описания его потока управления (как делать). Некоторые известные примеры декларативные доменные языки (DSL) включают CSS, регулярные выражения и подмножество SQL (например, выберите запросы) Многие языки разметки, такие как 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);

оба примера дают один и тот же результат, и один не лучше и не хуже другого. В первом примере требуется больше кода, но код тестируемый, и императивный подход дает вам полный контроль над деталь реализации. Во втором примере код, возможно, более удобочитаем; однако LINQ не дает вам контроля над тем, что происходит за кулисами. Вы должны верить, что LINQ предоставит запрошенный результат.


Я добавлю еще один пример, который редко появляется в обсуждении декларативного / императивного программирования: пользовательский интерфейс!

В C# вы можете создать пользовательский интерфейс, используя различные технологии.

на императивном конце вы можете использовать DirectX или OpenGL для очень императивного рисования кнопок, флажков и т. д... строка за строкой (или действительно треугольник за треугольником). Это до вас, чтобы сказать, как рисовать пользовательский интерфейс.

в декларативном конце у вас есть WPF. Вы в основном напишите XML (да, да," XAML " технически), и фреймворк сделает работу за вас. Вы говорите, как выглядит пользовательский интерфейс. Это зависит от системы, чтобы выяснить, как это сделать.

в любом случае, еще одна вещь, о которой нужно подумать. Просто потому, что один язык декларативен или императивен, не означает, что он не имеет определенных особенностей другого.

кроме того, одним из преимуществ декларативного программирования является то, что цель обычно легче понять из чтение кода в то время как императив дает вам более тонкий контроль над выполнением.

суть всего этого:

декларативный -> what вы хотите сделать

необходимо -> how вы хотите, чтобы это было сделано


все выше ответы и другие онлайн-сообщения упоминают следующее:

  • С декларативный Программирование, вы пишете код, который описывает то, что вы хотите, но не обязательно, как получить его
  • вы должны предпочесть декларативное Программирование императивному программированию

чего они нам не сказали, так это как этого достичь. Чтобы часть программы была более декларативной, другие части должны обеспечить абстракция чтобы скрыть детали реализации (которые являются важно кодексы).

  • например, LINQ является более декларативным, чем циклы (for, while и т. д.), например, вы можете использовать список.Где (), чтобы получить новый отфильтрованный список. Для того, чтобы это работало, Microsoft сделала всю тяжелую работу за абстракцией LINQ.

фактически, одна из причин, по которой функциональное программирование и функциональные библиотеки являются более декларативными, заключается в том, что они абстрагированы прочь петли и список творений, скрывая все детали реализации (скорее всего, императивные коды с петлями) за сценой.

в любой программе у вас всегда будут как императивные, так и декларативные коды, вы должны стремиться скрыть все важно коды за абстракциями, так что другие части программы могут использовать их декларативно.

наконец, хотя функциональное программирование и LINQ могут сделать вашу программу более декларативный, вы всегда можете сделать его еще более декларативным, предоставив больше абстракций. Например:

// JavaScript example

// Least declarative
var bestProducts = [];
for(var i = 0; i < products.length; i++) {
    var product = products[i];
    if (product.rating >= 5 && product.price < 100) {
        bestProducts.push(product);
    }
}


// More declarative
var bestProducts = products.filter(function(product) {
    return product.rating >= 5 && product.price < 100;
});

// Most declarative, implementation details are hidden in a function
var bestProducts = getBestProducts();

императивное программирование требует, чтобы разработчики определяли шаг за шагом, как код должен быть выполнен. Давать указания в императивной манере, ты говоришь :" поезжай на 1-ю улицу, поверни налево на главную, проедь два квартала., поверните направо на Мэйпл и остановитесь у третьего дома слева." Этот декларативная версия может звучать примерно так: "привод к Сью дом."Один говорит, как что-то сделать; другой говорит, что должно быть сделанный.

декларативный стиль имеет два преимущества перед императивным стилем:

  • это не заставляет путешественника запоминать длинный набор инструкций.
  • это позволяет путешественнику оптимизировать маршрут, когда это возможно.

Calvert, C Kulkarni, D (2009). Важное значение для LINQ. Эддисон Уэсли. 48.


мне понравилось объяснение из Кембриджского курса + их примеры:

  • декларативный - указать что делать не так сделать это
    • например: HTML описывает, что должно появиться на веб-странице, а не как это должно быть нарисовано на экране
  • важно - указать как что и как
    • int x; - что (декларативно)
    • x=x+1; - как

разница в основном связана с общим уровнем абстракции. С декларативным, в какой-то момент, Вы так далеко от отдельных шагов, что программа имеет много широты в отношении того, как получить результат.


вы можете смотреть на каждую часть инструкции как падающую где-то в континууме:

степень абстракции:

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

Декларативный Реальный Мир Пример:

  1. библиотекарь, пожалуйста, проверьте меня копию Моби Дика. (Библиотекарь, по своему усмотрению выбирает наилучший способ выполнения запроса)

Императивный Пример Реального Мира:

  1. идем в библиотеку
  2. найти систему организации книги (каталог карт-старая школа)
  3. исследование, как использовать каталоги карт (вы тоже забыли, правильно)
  4. выясните, как маркируются полки и организованный.
  5. выяснить, как книги на полке.
  6. расположение перекрестной ссылки из каталога карт с системой организации, чтобы найти указанную книгу.
  7. взять книгу, чтобы проверить систему.
  8. проверить книгу.

в информатике декларативное программирование-это парадигма программирования, которая выражает логику вычисления без описания его потока управления.

от http://en.wikipedia.org/wiki/Declarative_programming

в двух словах декларативный язык проще, потому что ему не хватает сложности потока управления ( циклы, операторы if и т. д. )

хорошее сравнение ASP.Net модель "code-behind". У вас есть декларативный.' Файлы ASPX, а затем императив " ASPX.Файлы CS коде'. Я часто обнаруживаю, что если я могу сделать все, что мне нужно в декларативной части сценария, гораздо больше людей могут следить за тем, что делается.


императивное Программирование говорит компьютеру явно, что делать и как это сделать, например, указание порядка и тому подобное

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)


кражу из Филип Робертс здесь:

  • императивное Программирование говорит машине, как что-то сделать (в результате чего вы хотите, чтобы произошло)
  • декларативное Программирование сообщает машине, что вы хотели бы сделать (и компьютер выясняет, как это сделать)

два примера:

1. Удвоение всех чисел в массив

обязательно:

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

обратите внимание, как императивные примеры включают создание новой переменной, ее мутацию и возвращение этого нового значения (т. е. как сделать что-то случиться), тогда как декларативные примеры выполняются на заданном входе и возвращают новое значение на основе на начальном входе (т. е. то, что мы хотим, чтобы произошло).


просто добавить еще один пример с точки зрения разработки мобильных приложений. В iOS и Android у нас есть интерфейсные строители, где мы можем определить пользовательский интерфейс приложений.

пользовательский интерфейс, нарисованный с помощью этих построителей, носит декларативный характер, где мы перетаскиваем компоненты. Фактический draeing происходит под и в исполнении концепции и системы.

но мы также можем нарисовать все компоненты в коде, и это необходимо по своей природе.

кроме того, некоторые новые языки как угловой JS фокусируется на разработке UIS декларативно, и мы можем увидеть много других языков, предлагающих ту же поддержку. Как JAVA не имеет никакого хорошего декларативного способа рисовать собственные настольные приложения в JAVA swing или JAVA FX, но в ближайшем будущем они просто могут.


императивное Программирование
Язык программирования, требующий дисциплины программирования, такой как C/C++, Java, COBOL, FORTRAN, Perl и JavaScript. Программисты, пишущие на таких языках, должны разработать надлежащий порядок действий для решения задачи, основанный на знании обработки данных и программирования.

декларативное Программирование
Компьютерный язык, не требующий традиционного написания логика программы; Пользователи концентрируются на определении входных и выходных данных, а не шагов программы, необходимых в процедурном языке программирования, таком как C++ или Java.

примерами декларативного программирования являются CSS, HTML, XML, XSLT, RegX.


декларативная программа-это просто данные для ее более или менее "универсальной" императивной реализации/vm.

плюсы: указание только данных в некотором жестко закодированном (и проверенном) формате проще и менее подвержено ошибкам, чем указание варианта некоторого императивного алгоритма напрямую. некоторые сложные спецификации просто не могут быть написаны напрямую, только в некоторой форме DSL. лучше всего и freq используется в структурах данных DSLs-это наборы и таблицы. потому что у вас нет зависимостей между элементами/строками. и когда у вас нет зависимостей, у вас есть свобода изменять и простота поддержки. (сравните, например, модули с классами - с модулями вы счастливы, а с классами у вас хрупкая проблема базового класса) все товары declarativeness и DSL немедленно вытекает из преимуществ этой структуры данных (таблицы и комплекты). еще один плюс-вы можете изменить реализацию декларативного языка vm, если DSL является более-менее абстрактным (хорошо спроектированным). сделайте параллельную реализацию, например. или перенесите его в другие os etc. все хорошие specifed модульные изолируя интерфейсы или протоколы дают вам такие свободу и easyness поддержки.

минусов: ты угадал. общий (и параметризованный DSL) императивный алгоритм/реализация vm может быть медленнее и/или память голодна, чем конкретный. в некоторых случаях. если такие случаи редки - просто забудьте об этом, пусть это будет медленно. если это frequient - вы всегда можете продлить свое гнездо DSL/ВМ для этого дела. где-то замедляя все остальные случаи, конечно...

П. С. Основы полпути между DSL и императив. и как все наполовину решения ... они сочетают в себе недостатки, а не преимущества. они не так безопасны и не так быстры :) посмотрите на jack-of-all-trades haskell - это на полпути между сильным простым ML и гибким Метапрограммным прологом... какое это чудовище. вы можете посмотреть на Prolog как Haskell с булевыми функциями/предикатами. и как проста его гибкость против Haskell...


Мне просто интересно, почему никто не упомянул классы атрибутов как инструмент декларативного программирования в C#. Популярный ответ этой страницы только что говорил о LINQ как инструменте декларативного программирования.

согласно Википедии

общие декларативные языки включают языки запросов базы данных (например, SQL, XQuery), регулярные выражения, логическое программирование, функциональное программирование и системы управления конфигурациями.

Так LINQ, как функциональный синтаксис, определенно является декларативным методом, но классы атрибутов в C#, как инструмент конфигурации, также являются декларативными. Вот хорошая отправная точка, чтобы узнать больше об этом:краткий обзор программирования атрибутов C#


насколько я понимаю, оба слова имеют корни в философии, есть декларативные и императивные знания. Декларативное знание-это утверждения истины, утверждения факта, подобные математическим аксиомам. Это говорит ты что-то. Императивное, или процедурное знание, говорит вам шаг за шагом, как прийти к чему-то. Вот что такое определение алгоритма по существу. Если хотите, сравните язык программирования компьютера с английским языком. Декларативная государственная предложений что-то. Скучный пример, но вот декларативный способ отображения того, равны ли два числа друг другу, в Java:

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

императивные предложения на английском языке, с другой стороны, дают команду или делают какой-то запрос. Императивное программирование-это просто список команд (сделайте это, сделайте то). Вот императивный способ отображения того, равны ли два числа друг другу или нет при принятии пользовательского ввода, в 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);
}

по сути, декларативные знания перескакивает некоторые элементы, чтобы сформировать слой абстракции над этими элементами. Декларативное Программирование делает то же самое.