Функциональное программирование - это такое ненужно в общем случае, когда решение задачи представляешь формулой. Иногда нужно, например при программировании на шаблонах C++, когда иных механизмов программирования времени компиляции нет.
Паскаль от С отличается уё..ой записью указателей, то есть ничем.
Давно ли в C завезли модули? А локальные процедуры и функции? (В крестах хотя бы лямбды сделали спустя 40 лет после паскалевских локальных процедур, но они анонимные, то есть опять-таки не совсем то.)
Например, есть «функциональная чистота», когда переменные присваиваются один раз и никогда больше не меняются. Это ограничение позволяет легко рассуждать о работе программ, т.е. это полезно. Я бы сказал, что это и есть функциональное программирование.
Есть «функции высшего порядка», когда можно передать параметр-функцию в функцию. Это можно в почти любом языке (Паскаль, Си и т.п.)
Есть «операции над функциями», например, композиция, когда на вход дают две функции, а на выходе получается новая функция - это тоже можно в почти любом языке.
Есть системы типов, которые часто приплетают сюда, но вообще они не имеют отношения.
Ещё говорят, что есть «чисто функциональные языки», например, Хаскель. Это неправда. Хаскель не является чисто функциональным языком, в нём всего лишь есть грань между чистым вычислением и вычислением с глобальным состоянием. Но эта неправда повторяется очень часто и можно запутаться.
Хаскель не является чисто функциональным языком, в нём всего лишь есть грань между чистым вычислением и вычислением с глобальным состоянием.
Тогда какой язык является чисто функциональным? И монада IO не «вычисление с глобальным состоянием», а такие же чистые вычисления, но внутри контейнера IO.
Кложуру освоить несложно. Вот хорошо её освоить — это уже другой вопрос.
Но так как Кложа крутится на JVM, лучше сперва освой жабу если время позволяет.
Меня Кложа сперва очень впечатлила, да, классный язык.
Накропал поделий и осознал, что за простым, читаемым кодом скрывается неповоротливое говно выжирающее память похлеще жабы.
а такие же чистые вычисления, но внутри контейнера IO.
Чистое вычисление можно повторить два раза и получить одинаковый результат. Если присоединить к COM порту пистолет, то в монаде IO можно отправить команду выстрелить. По вкусу, или в компьютер, или в себя. Это действие будет иметь существенные побочные эффекты, влияющие на результат при повторной попытке. Возможно, в Хаскеле эти вычисления _записаны_ как чистые. Не знаю деталей, но наверное, у нас есть какая-та функция, которая на входе принимает состояние и на выходе возвращает новое. На самом же деле она принимает лишь показания стрелки часов. Можно перевести часы назад, но в прошлое вернуться нельзя. Т.е. это лишь запись. Реальной власти над этими состояниями у программиста нет, нельзя вызвать вычисление дважды над тем же состоянием: оно разрушается в результате вычисления следующего состояния, и его никогда нельзя будет вернуть. Называть такие вычисления чистыми - это не ошибка, не условность, а просто ложь и сектантское искажение восприятия реальности.
Напишешь (compose f g) = (lambda (x) (f (g x))) на Си или Паскале?
Если сигнатура фиксирована, то напишу. Будет запись «композиция функций» с двумя полями: указателем на f и на g. И функция «вызвать композицию функций» с двумя параметрами: записью «композиция функций» и аргументом. Выглядеть это будет страшно, но по сути задача будет решена.
Вот про то и речь. Если язык позволяет вернуть именно функцию, а не НЁХ, для запуска которой надо вызывать специальную функцию, то он функциональный. Если приходится делать на каждый чих «вызвать композицию функций», «вызвать композицию композиций функций», «вызвать сечение функции», «вызвать связывание аргумента функции», то он не функциональный.
Тогда он сведётся к «вернуть пустую таблицу». Хотя нет. «Вернуть ошибку», CREATE TABLE ведь тоже нет...
На самом же деле она принимает лишь показания стрелки часов. Можно перевести часы назад, но в прошлое вернуться нельзя.
Немножко не так. Функции с побочными эффектами получают что угодно, а возвращают описание побочного эффекта. Например, main имеет тип IO (), то есть с точки зрения системы типов является просто константой. И в этой константе описаны побочные эффекты, генерируемые программой.
С точки зрения самой программы на Haskell мира не существует. Есть чистые функции. Есть константы. Константа с именем main содержит постоянное значение, описывающее взаимодействие с внешним миром.
Ну ладно, можно и это тоже считать частью определения функционального, но это всё же не то же, что «умение рассуждать о чистоте функций и возможность для пользователя задекларировать отличие чистых функций от грязных».
Нет, база уже должна быть, а потом мы её замораживаем и только select-ы. Или можно содержимое файла базы данных в качестве параметра передавать каждый раз.
а возвращают описание побочного эффекта
Ну если выстрел произведён, то описание побочного эффекта не полностью выражает этот побочный эффект. Возможно, что философия Хаскеля и замкнута в себе и её невозможно опровергнуть изнутри, как и любую религиозную философию. Но я нахожусь снаружи этой религии.
С точки зрения самой программы на Haskell мира не существует
Да, но выстрелить в себя (в компьютер) она, тем не менее может, после чего её не станет. Так что это представление неадекватно реальности.
с точки зрения системы типов является просто константой. И в этой константе описаны побочные эффекты, генерируемые программой.
Неважно, как программа это себе представляет. Чистое ФП по определению не имеет побочных эффектов, т.е. на практике их не имеет. В данном случае это не так. Далее, если программа на Хаскеле читает, то результат программы невозможно узнать без её конкретного запуска, причём, при двух разных конкретных запусках получатся разные результаты. Для чисто функциональной программы это так быть не должно.
Ну если выстрел произведён, то описание побочного эффекта не полностью выражает этот побочный эффект. Возможно, что философия Хаскеля и замкнута в себе и её невозможно опровергнуть изнутри
В программе нету «произвести выстрел». Там есть утверждение, что константа main содержит команду произвести выстрел. Будет ли кто-то исполнять эти команды для языка и системы типов Haskell неважно.
Чистое ФП по определению не имеет побочных эффектов, т.е. на практике их не имеет.
Так и не имеет. Программа на Хаскеле имеет не больше побочных эффектов, чем справочник по химическим реакциям. Побочные эффекты будет производить (возможно) читатель справочника. Сам справочник (или программа, возвращающая результатом этот справочник) побочных эффектов не производит.
можно и это тоже считать частью определения функционального, но это всё же не то же, что «умение рассуждать о чистоте функций и возможность для пользователя задекларировать отличие чистых функций от грязных»
Это именно про функциональность, а не про чистоту. Лисп всегда был функциональным языком, а чистые функции в нём до сих пор только в отдельных диалектах.
Побочные эффекты будет производить (возможно) читатель справочника. Сам справочник (или программа, возвращающая результатом этот справочник) побочных эффектов не производит.
Это верно для любой императивной программы, да и вообще для любой программы. Побочные эффекты производит не программа (файл), а среда выполнения, которая её выполняет.
Вот предлагаю критерий того, что программа чисто функциональная:
её результат детерминирован
результат можно мемоизировать
программа ничего не берёт из внешнего мира, кроме входных параметров, которые возможно предоставить до начала вычисления
программа ничего не меняет во внешнем мире, кроме затрат ресурсов на своё вычисление и возврата результата в конце вычисления
результат сам по себе пассивен и является данными. Если направить его в /dev/null, то в мире ничего не изменится,
только счётчик электричества немного накрутится
Для программы в IO неверно ни одно из этих утверждений. Что тогда позволяет называть её функциональной?
Лисп всегда был функциональным языком
Это вопрос терминологии. Я всегда считал и считаю, что CL - это императивный язык. Да, в нём есть лямбды, но ведь и лямбды в нём императивны. Из двух частей определения функциональности содержательной выглядит та, которая связана с чистотой функций, т.к. из этого следует много нетривиальных следствий (независимость результата от внешнего мира; отсутствие влияния на внешний мир, кроме возврата результата; детерминированность; мемоизация; возможность вычислений во время компиляции; возможность суждений о параллельности и т.п.). А отличие CL от Си ,когда он возвращает истинную функцию, а не какое-то мусорное ведро, как в моих эрзац-композициях - это вопрос терминологии (что называть функцией) и удобства (удобно ли вызывать эрзац-функцию). Никакой новой математики эта часть определения не добавляет. Поэтому если мы говорим о ФП по существу, я бы выделил именно чистоту.
Никакой новой математики эта часть определения не добавляет.
Всё таки, кроме математики, мы говорим о свойствах языка, т.е. о том что язык поддерживает данную концепцию как «родную». А это по сути и есть возможность написать compose f g = \х -> f $ g x вместо того чтобы городить огород. А то так и ассемблер и машинные коды можно назвать «функциональный язык», а чё, «написать же можно». Можно то можно, вот только через жопу, а значит поддержики данной концепции в языке нет, а зачем тогда называть язык «функциональным» если в нём чтобы скомпозировать ф-ции нужно плясать с бубном?
С другой стороны, по твоей логике си можно назвать «частично чистым ф-ным языкам», потому что ведь чистые ф-ции можно писать на си? Можно. Функции композировать можно? Можно.
Смысл в таком определении есть хоть какой нибудь? Должен же быть смысл в категоризации. Потому хаскель и относят к функциональным а си - нет.
Потому в хаскеле есть поддержка АТД, а в си - нет, хоть мы уже и выясняли с тобой, что ты можешь их нагородить из палок и работать вместо компилятора - но только это не сделать си поддерживающим АТД. Это скорее тебя сделает поддерживающим свою городульку эмулирующую АТД на си.
Мне кажется тебе надо с этим согласиться. Иначе ты в дебри какие то уходишь где у тебя собственная категоризация, но никто (в т.ч. и ты ) не знает какой от неё толк.
Это верно для любой императивной программы, да и вообще для любой программы.
Нет. В обычной программе ты не можешь управлять процессом формирования программы. А в Haskell результат программы лежит в константе main. И формирование этой константы является таким же чистым процессом, как формирование скомпилированного файла из текста программы. То есть, так как Haskell является чисто функциональным языком, то написать на нём можно только компилятор.
Я всегда считал и считаю, что CL - это императивный язык.
Если совсем строго, то мультипарадигменный. То есть и императивный и функциональный и декларативный и ООП...
Из двух частей определения функциональности содержательной выглядит та, которая связана с чистотой функций
В GCC есть __attribute__ ((pure)). но это не делает Си функциональным языком.
это вопрос терминологии (что называть функцией) и удобства (удобно ли вызывать эрзац-функцию)
Тебе на каждую операцию композиции придётся делать по отдельной эрзац-функции. И при вызове надо определять тип эрзац-функции и выбирать правильный пускатель. Или делать интерпретатор лиспа.
Если совсем строго, то мультипарадигменный. То есть и императивный и функциональный и декларативный и ООП...
Если совсем строго, то характеристика «императивный/декларативный» ортогональна свойствам «функциональный» и «ООП». В одном списке смешаны разные домены.
Eva, если ты всерьез, а в этом есть сомнения, то существует только один способ найти ответ. Это начать читать книги, прежде всего, по haskell, частично по clojure, ocaml, f# и, возможно, по common lisp и, может быть, scala. Закреплять практикой. А здесь тебя хорошему не научат. Уже понаписали всякую фигню
Конечно, образование должно быть в приоритете. А потом можно нагнать и программирование в любой момент. Но ЛОР точно не то место, где надо советоваться по базовым вопросам. Вот, подсказать какую-нибудь мелочь - с этим могут помочь
С другой стороны, по твоей логике си можно назвать «частично чистым ф-ным языкам», потому что ведь чистые ф-ции можно писать на си?
Да, с точки зрения функциональной чистоты Си - более функциональный, чем CL.
Мне кажется тебе надо с этим согласиться.
Я не соглашаюсь и не отрицаю, поскольку общепризнанного определения ФП нет. Есть набор мифов, в основном, сбивающих с толку. Поэтому я просто различаю «расширенный набор операций над функциями» и «поддержку чистых функций». Причём и то, и другое может заметно различаться от языка к языку, так что и здесь нет чёткости в терминологии. Например, я пытался понять, что значит «first class» functions. Определения этому нет, а те, которые есть - противоречивы. Должно быть определно API, интерфейс того, что можно делать с «first class» объектами, а такого определения нет. Так что не стоит вообще полагаться на терминологию в ИТ, ни на какую, особенно при принятии каких-то решений. Нужно смотреть на суть вещей.
То есть, так как Haskell является чисто функциональным языком, то написать на нём можно только компилятор.
Пропущу выкладки (тем более, там какие-то разрывы в логике наблюдаются) и отмечу, что вывод неверен. На Хаскеле написан, как минимум, один window manager, значит, где-то в твоей логике ошибка. Ну и опять же, смотря какой компилятор. Компилятор и даже «читатель» лиспа является императивным, а читатель, препроцессор и компилятор Си - функциональны (внезапно). И здесь уже никаких отступлений от буквы и духа.
Тебе на каждую операцию композиции придётся делать по отдельной эрзац-функции. И при вызове надо определять тип эрзац-функции и выбирать правильный пускатель.
Подходит под «вопрос удобства и терминологии». Очень неудобно, да. Но сделать можно, в принципе никаких _трудностей_ нет. А вот сможешь ли ты добавить в SBCL декларацию const? Это совсем не тривиально.
ну так я тебе и говорю - смотри на суть вещей, поймёшь почему так категоризируют. А ты «забыли дать определение, нет API, нипанятна, буду свою странную терминологию вводить, си более функциональный, лисп менее»
В одном из твоих последних тредов кто то сказал что спутал тред с тредом anonimous. Должен тебе скзатаь - это действительно весьма в его духе: цепляться к «формальностям», полностью игнорируя суть, чем, на мой взгляд, ты занимаешься последнее время чаще. Хотя может ты всегда так делал, а я просто незамечал.
ха-ха, ну нет «же определения, а те что есть противоречивы», это я про конпелятор, гыгы, пойди докажи ему теперь что на хаскеле что то кроме компилятора написано, если он своё понимание компилятора вводит.
можно(что почти но не тоже самое что тобое указаное) считать если в языке есть синтаксис в котором не отличима своя композиция от обычных(т.е системных и пользовательских) функций.
можно же считать что синтаксис данного(конкретного языка) всё равно не совершеннен и допускать для себя возможность заката солнца в ручную по необходимости - а не бегать с криком что данный язык оцтой.
понятно что лучше специализированный инструментарий чем одно ацкое комбайнен.