Функциональное программирование |
Функциональное программирование всегда привлекало меня в противопоставлении к императивному.
Я очень часто обсуждаю различные аспекты функционального программирования на различных ветках на Базарной площади.
Но хотелось бы собрать всех заинтересованный этой темой в одной ветке.
Я думаю что настало время открыть такую тему. И вот почему.
Исторически функциональное программирование появилось практически вместе с императивным.
Вторым языком после фортрана был лисп.
Но увы, функциональное программирование надолго было уделом исследовательских институтов или специализированных приложений (Искусственный Интеллект)
Конечно не надо считать весь мир дураками из за того что развитие пошло по пути языков Алгол семейства.
Для этого были вполне обьективные причины. Функциональные языки слишком близки к человеку и слишком далеки от машины.
Они сьедают в десятки раз больше рессурсов чем императивные языки.
Вспомните претензии, предявляемые к java - первому императивному языку с виртуальной машиной и сборщиком мусора, толкаемому большими корпорациями в mainstream.
Жутко тормозит, и жрет всю память какая есть. А ведь функциональные языки (далее ФЯ) все без иключения имеют сборщик мусора, виртуальную машину.
Многие из них (семейство лисп) еще и динамические, что только усугубляет положение.
Вполне естественно что появившись более полусотни лет назад они надолго опередилли свое время.
Для широкого распространения ФЯ нужны гигабайты дешевой памяти и гигагерцы дешевых процессоров.
Прошло более 50 лет, прежде чем такие требования к железу стали реальностью.
Это время наступило. СЕЙЧАС.
Добро пожаловать в новую эру программирования.
Jack Of Shadows
Всего в теме 5502 сообщения
Добавить свое сообщение
Отслеживать это обсуждение
- Средства разработки. Языки программирования.
- Delphi 4 or Delphi 5
- Что приобрести в качестве средства разработки?
- Delphi6
- Delphi vs PowerBuilder
- Сравнение компиляторов
- Вот и вышла Delphi 7... Вы рады?
№ 562 02-08-2006 14:46 | |
Тут у вас была дисскусия, идентичны ли передача макросу куска кода и передача процедуре (в качестве аргумента) локальной процедуры, такой же код реализующий...
Какое отличие в форме записи?
По-моему, отличие только в том, что при передаче кода этот код описывается в месте его передачи, а при передаче процедуры этот код описывается чёрти где от места его передачи.
То есть передача процедуры в данном случае может быть менее наглядной: что бы понять, что конкретно в этом месте происходит, придётся отмотать текст программы назад, и не известно ещё на сколько десятков или сотен строк назад...
В языке Алгол-68 это не так страшно - описал локальную процедуру прямо в списке аргументов другой процедуры и тут же её передал.
Или просто взял и передал кусок кода какой-нить процедуре! :-)
Попробуйте повторить это в Дельфах:
INT x = 5;
PROC fact = (INT n) INT: IF n < 2 THEN 1 ELSE n * fact(n-1) FI;
# bla-bla-bla на 1000 строк #
# Передача процедуры в стандартном виде #
print (("fact(", x, ") = ", fact(x), new line));
# -----------------------------------------------------------
Передача процедуры, описанной в параметрах другой процедуры #
print (("fact(", x, ") = ",
( # Описание локальной передаваемой процедуры,
с опциональным доступом к локальным переменным : #
PROC f = (INT n) INT: IF n < 2 THEN 1 ELSE n * f(n-1) FI;
f(x) # Собственно сама передача процедуры #
),
new line
));
# Здесь уже процедура f(n) недоступна - её использование даст ошибку типа
error: identifier `f' has not been declared in this range #
# А можно в параметрах процедуры просто указать последовательность операторов: #
print (("fact(", x, ") = ", # Ну, чем не макрос? ;-) #
(
INT n := 1;
FOR i TO x DO n *:= i OD;
n
),
new line
))
Результат у всех трёх вариантов одинаковый:
fact( +5) = +120
fact( +5) = +120
fact( +5) = +120
Нечто подобное приводил Trurl (пример queens).
Алгол-68 - гимнастика для ума! Только не называйте это интеллектуальным онанизмом! :-)
Всё-таки стоит возродить Алгол-68... :o)
№ 561 02-08-2006 13:31 | |
Новенькая статья Джоела Спольски : http://www.joelonsoftware.com/items/2006/08/01.html
Can Your Programming Language Do This?
О чем он там говорит ? Да о том же о чем мы здесь говорим :))
Сначала приводит примеры анонимных функций и передачу их как параметров.
Затем обьясняет почему анонимные классы в java, ну и соотвественно аналогичные механизмы в сишарп, не являются аналогичной заменой (это вам hugi, знаю что не убедит, просто пример еще одного человека думающего не так как вы.)
После чего Джоел говорит об автоматическом распараллеливании функционального кода, и конкретно о функциональном языке MapReduce, созданном Google именно для автоматического распараллеливания.
О корнях MapReduce (да, да ЛИСП!)
О том что ООП и ФЯ мягко говоря несовместимы, и что если вы приняли на веру ООП, то это сильно ограничивает ваши возможности как программиста.
Вспомнил еще одну интересуную статью Пола Грехема.
Ссылку на нее здесь уже кто то давал.
Но приведу еще раз с кратким обьяснением о чем она.
http://www.paulgraham.com/avg.html
Пол Грехем говорит о парадоксе Блаб, как он его называет.
Представим себе что программист работает на языке Блаб.
Язык Блаб далек от ассемблера, но в то же время не такой уж и высокоуровневой (аналог java сишарп и прочих ИЯ)
То есть располагается в спектре языков где то посередине.
Программист Блаб может смотреть по спектру вниз и корректно судить о более низкоуровневых языках (COBOL, си ) Он видит то чего там нет, и что есть у него.
Но смотреть по спектру языков вверх не может. Ему кажется что он там ничего не видит. Ведь он все может делать на своем языке, значит наверху ничего того что ему понадобилось бы - нет.
Убеждать его при этом бесполезно. Не имея личного опыта с ФЯ, он всегда приведет вам "функционально идентичный" код, на любой ваш пример.
Только на практике такой Блаб программист может убедиться что ФЯ дают ему то что у него никогда не было в его Блаб языке.
Но кто из них когда либо утруждал себя практикой ? :))
№ 560 01-08-2006 12:59 | |
Ответ на »сообщение 556« (Geniepro)
___________________________
Правильно ли я понимаю, что (почти) любую структуру данных в Лиспе можно представить в виде списка (не уверен насчёт сетей, но, наверное, и их тоже можно),
Теоретически, да. Но на практике ИМХО в большинстве случаев скорее всего будет достаточно воспользоваться стандартными структурами данных, которые имеются в любой ANSI-совместимой Лисп-системе: векторами, многомерными массивами, хэш-таблицами, структурами (кортежами). Списки, естественно, тоже никто не запрещает, но использовать их нужно к месту.
а простые типы являются по сути атомами, о которых можно узнать, как они конкретно представляются или обозначаются на машинном уровне (хотя бы с помощью функции type-of)?
Вообще говоря, атомами являются не только простые типы. Например, массив это тоже атом.
№ 559 01-08-2006 12:32 | |
Ответ на »сообщение 558« (hugi)
___________________________
И здесь имеет значение именно семантическая эквивалентность реализаций, а никак не форма записи.
(хотя, безусловно, форму тоже нельзя игнорировать, но тем не меннее семантика понятия всегда имеет приоритет перед его синтаксическим отражением).
Скажите это создателям языков которые добавляют в свои языки case, хотя у них уже есть семантически эквивалентная конструкция if
case x of
2: begin
...
end
3: begin
...
end
4: begin
...
end
5: begin
...
end
end
и
if x = 2 then
begin
...
end
else if x = 3 then
begin
...
end if x = 4 then
begin
...
end if x = 5 then
begin
...
end
Видите ли, семантически разницы между этими двумя примерами нет никакой. Даже в количестве символов они гораздо более близки чем наш с вами пример с closures и локальными функциями. Более того обе конструкции являются высокоуровневыми. Таким образом, согласно вашей логике, они идентичны и следовательно между языками в которых есть case и нет case - никакой разницы нет.
Все до единого корифеи программирования, включая Вирта, Гослинга, Андерса Хейлберга, Алана Кея, и конечно же моего обожаемого Маккарти - с вами в этом не согласны. У них у всех есть case вместе с if.
Убедить вас в важности различия в форме записи я не могу. В конце концов это не теорема со строгим математическим доказательством.
Могу лишь указать что огромное количество людей, включая все ключевые фигуры в программировании, считают разницу в форме записи достаточно важной, чтобы включать в язык некоторые конструкции.
Так что мы с вами просто останемся каждый при своем мнении.
Я принадлежу к тем людям которые считают что форма записи в языке решающая.
Потому что речь идет не о потенциальном, теоретическом поле возможных решений, которое у всех языков одинаково, а о практическом, доступном человеку поле решений, которое у всех языков различается именно из за разницы в форме записи.
№ 558 01-08-2006 11:10 | |
Ответ на »сообщение 548« (Jack Of Shadows)
___________________________
Способом записи. Функционально однозначны, о том и речь.
Это как 5 + 4 отличается от Add(5,4) - форма записи разная, однако функционально однозначны.
Т.е., если я скажу, что в Лиспе нет операции сложения, потому что операция сложения это именно 5 + 4, а не + 5 4, то буду прав? Или closures в Ruby, closures в Лисп и closures в Smalltalk -- это не одно и то же потому что у них разные формы записи?
Приводить примеры функционально идентичного кода вообще бессмысленно, поскольку как я уже говорил, любой turing complete язык можеь сделать все что сделает другой такой же turing complete язык.
Вот опять Вы подменяете одну проблему другой. Когда говорят о взаимозаменяемости различных формализаций понятия "алгоритм" и соответствия какого-либо ЯВУ одному из формализмов, имеют в виду т.н. мощность языка, т.е. множество потенциально решаемых с его помощью задач. Согласно этому критерию, естественно, все языки равны между собой. Но мы сейчас обсуждаем не круг решаемых задач, а конкретный способ решения, т.е. очень высокоуровневое понятие и реализации этого понятия в различных языках программирования. И здесь имеет значение именно семантическая эквивалентность реализаций, а никак не форма записи. Вот как раз споры о форме записи и есть пресловутое противопоставление begin/end фигурным скобкам. Да, возможно, синтаксис одного из языков более удобен для представления closures, чем синтаксис другого, но это вопрос скорее личных симпатий и предпочтений, и, на мой взгляд, лучше остановиться на смысле понятий, а не на их форме (хотя, безусловно, форму тоже нельзя игнорировать, но тем не меннее семантика понятия всегда имеет приоритет перед его синтаксическим отражением).
№ 557 01-08-2006 10:29 | |
Ответ на »сообщение 551« (Jack Of Shadows)
___________________________
Многое из вашего поста уже говорилось здесь причем не раз.
За несколько дней чтения этой ветки я успел осилить только две трети.
Только сейчас я начал подходить к тем местам, где это было явно сказано...
Потому и извинился заранее за возможный флуд... ;-)
Окей, углубляюсь в дальнеёшее чтение. :-) Сорри за оффтоп...
№ 556 01-08-2006 09:39 | |
Ответ на »сообщение 555« (Lisp Hobbyist)
___________________________
Учитывая, что в массе своей читатели этой ветки с современным состоянием дел в мире Лиспа не слишком знакомы и знакомиться не собираются,
Ну, если бы я не интересовался функциональным программированием, я бы сюда вообще не заглянул бы. Следовательно, не только собираюсь, а УЖЕ интересуюсь...
ИМХО, слишком велик риск, что из таких умолчаний они сделают тот вывод, который я и наблюдаю в течение всей этой дискуссии --- что если Лисп на что и годится, так это на слишком экзотические вещи, которые лично им никогда не понадобятся.
А вот этого лично я не утверждал!
Хотя мне лично и не приходилось решать задачи с помощью Лиспа - просто не было такой необходимости по работе да и инструментов, а как хобби на листке бумаги - не совсем серьёзно...
Современный ANSI Common Lisp предусматривает большое количество встроенных типов данных.
Правильно ли я понимаю, что (почти) любую структуру данных в Лиспе можно представить в виде списка (не уверен насчёт сетей, но, наверное, и их тоже можно), а простые типы являются по сути атомами, о которых можно узнать, как они конкретно представляются или обозначаются на машинном уровне (хотя бы с помощью функции type-of)?
Возможно, моя герменевтика меня подводит, но по-моему, в первоначальном сообщении сначала было сказано насчет ограниченности Лиспа символьными манипуляциями, а лишь затем о языковых процессорах. По-моему, это ни что иное, как посылка (ограниченность) и следствие (предложение "ниши", в которой этот язык окажется на высоте).
А что есть обработка данных, как не манипуляции с символами "0" и "1"?
С этой позиции, ВСЕ языки программирования ограничены - ведь везде всё сводится к перетасовыванию нулей и единиц...
Я нигде не утверждал, что Лисп - ограниченный язык, наоборот, я вроде упомянул, что Лисп может симитировать всё, что угодно, было бы желание. Как, впрочем, и любой другой язык...
Вот скажите, какие задачи Вам конкретно приходится решать по работе или как хобби?
Разве нельзя назвать их задачами преобразования данных, оценки каких-то факторов и принятия каких-либо решений?
ЗЫ. Уж как я старался быть осторожным в своих высказываниях, и то не помогло... :-)
№ 555 01-08-2006 07:22 | |
Ответ на »сообщение 554« (Jack Of Shadows)
___________________________
Я полагаю что Geniepro в курсе. :)) Он же написал что утрирует.
И почему тоже написал.
Возможно, моя герменевтика меня подводит, но по-моему, в первоначальном сообщении сначала было сказано насчет ограниченности Лиспа символьными манипуляциями, а лишь затем о языковых процессорах. По-моему, это ни что иное, как посылка (ограниченность) и следствие (предложение "ниши", в которой этот язык окажется на высоте). Таким образом, объяснения, почему можно так утрировать, я не вижу.
Впрочем, заниматься телепатией и гадать "знает/не знает" я не хочу. Вопрос в другом: насколько уместно такое "утрирование", так сказать, "в гостях"? Учитывая, что в массе своей читатели этой ветки с современным состоянием дел в мире Лиспа не слишком знакомы и знакомиться не собираются, ИМХО, слишком велик риск, что из таких умолчаний они сделают тот вывод, который я и наблюдаю в течение всей этой дискуссии --- что если Лисп на что и годится, так это на слишком экзотические вещи, которые лично им никогда не понадобятся.
Речь идет об обработке лиспового кода как списка. А там действительно - атомы и списки, и больше ничего.
Можно сказать и так, но в реальной ситуации, боюсь, придется анализировать более конкретные типы. В качестве иллюстрации
(defun list-to-types (x)
(cond
((listp x)
(loop for i in x collect (list-to-types i)))
(t
(type-of x))))
...
> (list-to-types '(defun f (x) (aref #("abc" 3 #C(2.7 1)) (+ x 3))))
(SYMBOL SYMBOL (SYMBOL)
(SYMBOL (SIMPLE-VECTOR 3) (SYMBOL SYMBOL (INTEGER 0 16777215))))
Если функциональность нашего языкового процессора ограничивается, например, простейшими текстовыми манипуляциями, конкретные типы элементов списка действительно имеют небольшое значение. Но если мы пишем, к примеру, type inferencer, то здесь очень даже придется отличать символы от прочего, по значениям числовых констант (которые, в свою очередь, придется выделять в тексте) строить оценки диапазонов значений переменных и тому подобное.
№ 554 01-08-2006 03:13 | |
Ответ на »сообщение 553« (Lisp Hobbyist)
___________________________
Современный ANSI Common Lisp предусматривает большое количество встроенных типов данных.
Я полагаю что Geniepro в курсе. :)) Он же написал что утрирует.
И почему тоже написал.
Речь идет об обработке лиспового кода как списка. А там действительно - атомы и списки, и больше ничего.
№ 553 01-08-2006 02:29 | |
Ответ на »сообщение 550« (Geniepro)
___________________________
Когда в языке только (утрированно) два типа данных (атомы и списки) и, соответственно, только операции склеивания/разрезания/вычисления списков - естественно, "обычным" программистам трудно представить себе, что это такое и как с этим можно что-то сделать... Стереотипы, как тут уже упоминалось...
Очень жаль, что "обычные" программисты продолжают судить о языке по книгам/лекциям середины 70-х годов.
Современный ANSI Common Lisp предусматривает большое количество встроенных типов данных.
http://www.lisp.org/HyperSpec/Body/sec_4-2-3.html#standardizedatomictypespecs
Добавить свое сообщение
Отслеживать это обсуждение
Дополнительная навигация: |
|