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

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

+464
источник поделиться
16 ответов

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

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

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

+689
источник

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

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

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

SELECT score FROM games WHERE id < 100;

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

+127
источник
другие ответы

Связанные вопросы


Похожие вопросы

Декларативный и императивный

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 odd"
var evenNumbers = numbersOneThroughTen.Select(number => number % 2 == 0);

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

+93
источник

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

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

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

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

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

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

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

Декларативный → what, который вы хотите сделать

Императив → how вы хотите сделать это

+42
источник

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

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

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

  • Например, LINQ более декларативен, чем циклы (for, while и т.д.), Например, вы можете использовать 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();
+42
источник

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

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

Императивное программирование требует от разработчиков поэтапного определения того, как код должен быть выполнен. Чтобы дать указания в императивной манере, вы говорите: "Идите на 1-ю улицу, поверните налево на главный, проведите два блока, поверните направо на Клен и остановитесь в третьем доме слева. декларативная версия может звучать примерно так:" Привести к судам дом ". Говорят, как что-то сделать, а другой говорит, что нужно сделал.

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

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

Calvert, C Kulkarni, D (2009). Основной LINQ. Эддисон Уэсли. 48.

+22
источник

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


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

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

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

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

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

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

  • Войдите в библиотеку
  • Найти систему организации книг (Каталог карт - Старая школа)
  • Исследование использования карточных каталогов (вы тоже забыли).
  • Определите, как полки помечены и организованы.
  • Выясните, как книги организованы на полке.
  • Расположение перекрестных ссылок из каталога карт с системой организации, чтобы найти указанную книгу.
  • Возьмите книгу, чтобы проверить систему.
  • Ознакомьтесь с книгой.
+16
источник

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

С#:

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

Декларативный - это когда вы говорите компьютеру, что делать, но не так, как это сделать. Datalog/Prolog - это первый язык, который приходит на ум в этом отношении. В основном все декларативно. Вы действительно не можете гарантировать порядок.

С# - гораздо более императивный язык программирования, но некоторые функции С# являются более декларативными, например 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}
     )

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

+10
источник

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

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

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

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

+8
источник

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

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

Два примера:

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

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

+7
источник

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

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

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

+4
источник

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

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

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

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

+2
источник

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

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

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

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

+2
источник

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

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

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

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

+2
источник

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

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

+1
источник

Посмотрите другие вопросы по меткам или Задайте вопрос