Как стать автором
Обновить

Классификация парадигм программирования

Уровень сложностиПростой
Время на прочтение6 мин
Количество просмотров4.9K
Всего голосов 29: ↑23 и ↓6+19
Комментарии50

Комментарии 50

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

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

На самом деле, один и тот же код может иметь денотационную и операционную семантику. Если мы рассматриваем его денотационную семантику, то он кажется нам декларативным, а если операционную - то, соответственно, императивным.

Что касается классификации, то я бы ещё добавил статический/самомодифицирующийся код.

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

Императивное целеполагание

Конкретные инструкции исполнителю по достижению результата.

X(a,b,c) := ( -b ± sqrt( b^2 - 4*a*c ) )/( 2*a )

Приведена функция. Она ни декларативная ни императивная

Даже здесь можно сначала вычислить сначала из этих вариантов

b^2 или 4*a или a*c

А вам известно что такое оптимизирующий компилятор?

Он поменяет последовательность вычислений в императивном коде по вашей классификации

Кстати, можно договориться, что все красные функции делаем асинхронными, тогда для всех красных придется писать async await вплоть до main. Очень удобно, вернее обычно у компилятора просто нет других способов.

А вы статью читать не пробовали перед написанием комментариев?

Нет, я просто придираюсь к одной вашей фразе. Но раз взялись за классификатор то надо соответствовать

Теперь прочитал. Но, кхм...

Не стоит рассчитывать что оппонент прочитает простыню по вашей ссылке, а потом грубо спрашивать за прочтение. Я не студент, вы не лектор.

Я ответил то что знал и без статьи. Что это есть в ней - ну, я рад.

мне всегда было интересно, а что такое математические операции в функциональном вычислении, например здесь:

one := 1 // one = 1

next( prev ) := prev + one

что такое "+", это же вроде бы не функция? А что это такое? Где у них типа-безопасность, например?

Вроде как функциональные вычисления тоже не совсем функциональные?

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

Это синтаксический сахар для функций.

это мой любимый термин и любимый ответ! Что называется: "Вот и поговорили..."! :)

Видимо, я попался на крючок, подсекайте.

next( prev ) := prev + one
что такое "+", это же вроде бы не функция? А что это такое? Где у них типа-безопасность, например?

Вроде как функциональные вычисления тоже не совсем функциональные?

Там конечно надо смотреть исходники, вероятно, какой-нибудь Scala, где, скорее всего, после устранения сахара, окажется что-то вроде:
next( prev ).assign(prev.plus(one))

Буквально: ":=" - это метод объекта, который вернуло выражение next( prev ). А "+" - это метод объекта prev. Обеспечению типобезопасности тут синтаксис никак не мешает. Нужно всего лишь смириться, что привычные символы могут означать что-то очень необычное, просто потому, что так решил автор конкретного метода "+".

а вот здесь вот:

prev.plus

а это что за операция "." ?

Как по мне здесь:

next( prev ).assign(prev.plus(one))

сахара стало больше, очень похоже на устранение сахара с помощью сахарного песка.

Вы утверждаете, что после устранения сахара (записи вызова метода в синтаксической форме инфиксного оператора) сахара стала больше. Позвольте поинтересоваться, что Вы считаете сахаром, что - сахарным песком? И как их отличаете от "безуглеводного" кода?

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

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

Что это за язык и что обозначает ":=" ? Если это присваивание, то тут нет ничего функционального.

А "+" – обычная функция, записанная в инфиксной форме. У утончённых людей это (+ prev one).

В данном случае это связь имени с выражением.

Во втором случае слева не имя.

Связь имени с выражением - это, например,

(let
 ((one 1))
 (+ one 2))

то есть "обозначим 1 как one и в этом контексте вычислим значение формы (+ one 2)".

А там где функциональная форма?

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

Именованные функции - вообще зло, если подходить с пуристских позиций.

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

Никаких объявлений в парадигме нет. Функциональная парадигма - это аппарат лямбда-исчисления (о чём писал Плоткин в своей эпохальной работе "Лямбда-исчисление как язык программирования", которую принято цитировать по любому поводу). Но есть синтаксический сахар в функциональных языках, потому что на голом лямбда-исчислении писать тяжко. В данном случае этот сахар имеет императивную природу, так как такое объявление модифицирует окружение.

Разве алиасы запрещены в ФП?

Пока не пытаемся переприсвоить имя, не должны влиять.

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

(let
 ((one 1))
 (f one))

->

((lambda (one)
  (f one)) 1)

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

Тут вы просто поменяли раннее связывание имени со значением на позднее. Если хотите совсем от имён избавиться, то вам к эзотерическим языкам типа Unlambda.

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

К связыванию это не имеет вообще никакого отношения. Хотите связывайте рано, хотите – поздно, ничего в этих формах не изменится. Это две полностью семантически эквивалентные формы.

Лямбда-исчисление – это раздел математики, лежащий в фундаменте функционального программирования и придающий ему какое-либо содержание вообще. Если что-то не выражается непосредственно в формализме лямбда-исчисления, то это что угодно, но точно не ФП.

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

Ну и чего вы тогда докопались до моего оператора раннего связывания?

А аксиомы Пеано лежат в фундаменте арифметики. Значит ли это, что формализация числа 3 через { { { 0 }, 0 }, 0 } вместо ( 1 + 1 ) + 1 - это уже что угодно, но не арифметика?

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

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

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

Вот вам два эквивалентных кода:

one := 1
two := one + 1
( one => ( two => two )( one + 1 ) )( 1 )

Ну N равномощно Z, а там уже чисто техническая сложность. Хотите по спирали обходите, хотите кодируйте в прямом коде, дописав знак в виде второго элемента множества.

Что касается фрагментов кода. Они не эквивалентны, потому что у первого область видимости one и two продолжается дальше вниз, а у второго заканчивается. Это вообще характерная для ФП проблема глобального контекста.

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

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

Конечным алгоритмом никакое бесконечное множество в принципе не построить.

У вас фамилия не Мюнхгаузен случаем?

Никакое одно из этих чисел в отдельности невозможно построить конечным алгоритмом.

Множество чисел, которые можно актуально построить - равномощно Z. Но это бесконечно малая часть C.

А все-таки, что это за язык?

Bogus

Т.е. Вы решили для демонстрации функционального стиля придумать оператор ":=", который у людей ассоциируется в первую очередь с присваиванием в процедурных языках? Ну ОК. Хотя, на мой взгляд, вопросов было бы меньше, если бы Вы использовали синтаксис какого-нибудь существующего языка или хотя бы использовали разные обозначения для оператора присваивания значения переменной и оператора именования выражения. Например, так:

// Функциональное вычисление
def next( prev ) = prev + 1
def state = 1
def newState = next( state )
// Процедурное вычисление
def next( prev ) = prev + 1
state := 1
state := next( state )

Спасибо, им от меня тоже привет. В последнем, к слову, Ваша идея о неизменности состояния тоже демонстрируется нагляднее, чем в Bogus:

// Функциональное вычисление
const next = ( prev ) => prev + 1
const state = 1
const newState = next( state )
// Процедурное вычисление
const next = ( prev ) => prev + 1
let state = 1
state = next( state )

В JS декларации (const, let, function и т.д.) не менее важны, чем присваивание (=), на которое Вы сослались.

А вообще, не очень понимаю этот Ваш комментарий. Я даю конструктивное предложение, как улучшить форму подачи Ваших идей для читателя, а Вы мне приветы передаете.

Если не трудно, дайте определения терминам "определение" и "парадигма", которые вы использовали при написании статьи?

Определение парадигмы есть в самом начале статьи.

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

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

Про определение определения выяснить, вот что самое интересное.

Так не любой подход же. Углубляться тут в философию можно долго и так никуда и не прийти.

Мне очень понравилось, как вы написали "всякое определение должно иметь чёткую границу между тем, что ему соответствует, и тем, что не соответствует.".

Я сам когда-то этим озаботился. Это самая настоящая проблема для разработчика, и осознание этого двинуло меня в поиски. А они привели меня к известной системе логических категорий, в которой чётко уложены и "определения", и "границы" и всё остальное. В этой точке я осознал, что нашёл какие-то "марсианские артефакты" и теперь думаю, что с этим делать )))

Система логических категорий Г.Ф.В.Гегеля, пресловутая диалектика, "Наука логики".

556 страниц отборных нейро-галлюцинаций.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации