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

StackOverflow https://stackoverflow.com/questions/1784664

Вопрос

Я искал в Интернете определения декларативного и императивного программирования, которые пролили бы для меня некоторый свет.Однако язык, используемый на некоторых ресурсах, которые я нашел, устрашает - например, на Википедия.Есть ли у кого-нибудь реальный пример, который они могли бы показать мне, который мог бы внести некоторую перспективу в эту тему (возможно, на 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 знает, что это идеальное время для использования всех 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 более декларативен, чем петли (для, в то время как и т. Д.), Например, вы можете использовать list.Where() Чтобы получить новый фильтрованный список. Чтобы это работало, Microsoft проделала всю тяжелую работу за абстракцией LINQ.

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

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

Наконец, хотя функциональное программирование и 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();

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

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

Императивное программирование требует, чтобы разработчики определяли шаг за шагом, как следует выполнять код. Чтобы дать указания императивным образом, вы говорите: «Идите на 1 -й улицу, поверните налево на Main, проезжайте два блока, поверните направо на клен и остановитесь в третьем доме слева». Декларативная версия может звучать примерно так: «Поездка в дом Сью». Один говорит, как что -то сделать; Другой говорит, что нужно сделать.

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

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

Calvert, C Kulkarni, D (2009). Essential Linq. Аддисон Уэсли. 48

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


Вы могли бы посмотреть на все инструкции как падение где -то на континууме:

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

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

Декларативный пример реального мира:

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

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

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

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

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

(Пример из Википедии Линк)

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

Из http://en.wikipedia.org/wiki/declarative_programming

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

Хорошее сравнение-модель ASP.NET 'Code-Behind'. У вас есть декларативные файлы. Я часто обнаружил, что если я могу сделать все, что мне нужно в декларативной половине сценария, может следовать тому, что делается.

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

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

Два примера:

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

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

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

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

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

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

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

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

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

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

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

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

P.S.Frameworks находится на полпути между DSL и императивом.и как все половинчатые решения...они сочетают в себе недостатки, а не преимущества.они не такие безопасные И не такие быстрые :) посмотрите на универсальный Haskell - это что-то среднее между сильным простым ML и гибким метапрогом Prolog и...что это за монстр.вы можете рассматривать Пролог как Haskell с логическими функциями/предикатами.и насколько проста его гибкость по сравнению с Haskell...

I just wonder why no one has mentioned Attribute classes as a declarative programming tool in C#. The popular answer of this page has just talked about LINQ as a declarative programming tool.

According to Wikipedia

Common declarative languages include those of database query languages (e.g., SQL, XQuery), regular expressions, logic programming, functional programming, and configuration management systems.

So LINQ, as a functional syntax, is definitely a declarative method, but Attribute classes in C#, as a configuration tool, are declarative too. Here is a good starting point to read more about it: Quick Overview of C# Attribute Programming

From my understanding, both terms have roots in philosophy, there are declarative and imperative kinds of knowledge. Declarative knowledge are assertions of truth, statements of fact like math axioms. It tells you something. Imperative, or procedural knowledge, tells you step by step how to arrive at something. That's what the definition of an algorithm essentially is. If you would, compare a computer programming language with the English language. Declarative sentences state something. A boring example, but here's a declarative way of displaying whether two numbers are equal to each other, in Java:

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

Imperative sentences in English, on the other hand, give a command or make some sort of request. Imperative programming, then, is just a list of commands (do this, do that). Here's an imperative way of displaying whether two numbers are equal to each other or not while accepting user input, in 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);
}

Essentially, declarative knowledge skips over certain elements to form a layer of abstraction over those elements. Declarative programming does the same.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top