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


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

16 407

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.

SELECT score FROM games WHERE id < 100;

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

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

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

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

оба примера дают один и тот же результат, и один не лучше и не хуже другого. Первый пример требует больше кода, но код проверяемых, и императивный подход дает вам полный контроль над деталь реализации. Во втором примере код, возможно, более читаем; однако 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). Essential 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 у нас есть интерфейсные строители, где мы можем определить пользовательский интерфейс приложений.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

public static void main(String[] args)
{
    System.out.print("4 = 4.");
}
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);
}

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