Функциональный язык — тот, в котором основная парадигма функциональная. Языков, в которых совсем невозможно ФП, по-моему, уже и нет, даже Java не устояла. С ООП то же самое, ООЯП — тот, в котором основная парадигма объектно-ориентированная. Но языков, в которых невозможно ООП, тоже практически нет.
Другими словами, вопрос только в качестве, удобстве и полноте поддержки той или иной парадигмы в языке.
Попробуйте реализовать построение суффиксного дерева на функциональном чистом языке за линейное время. Я вот ещё ни одной реализации не встречал. А на императивных «грязных» языках — запросто.
Я уже несколько раз тут в комметах писал… не надо пытаться реализовывать императивные алгоритмы в функциональном стиле. Ничего хорошего из этого не получится. И это ни разу не аргумент против ФП.
Я не улавливаю Вашей логики, честно говоря. В научных расчётах много чего используется, в том числе и ФП. Только какой от этого практический толк, если, допустим, Вы не занимаетесь научными расчётами?
Мне вот интереснее применение ФП для таких проектов как WhatsApp, Twitter и т.д.
Ok. Я просто когда-то давно тоже программировал на Delphi, но практически все, кого я знал, перешли на C# в районе 2007-2009 годов. Хотя, косвенно hh.ru это подтверждает, по тому же C# почти в 8 раз больше вакансий )
Вообще-то, конкурентность и параллелизм — это совсем разные понятия. Параллелизм тоже можно устроить на ФП, но я это не имел в виду в начальном сообщении.
Про программирование на GPU я Вам не подскажу, т.к. не интересуюсь этой темой. Если Вы хотели подколоть на тему, что для параллелизма есть инструменты получше, то вспомнили бы лучше Lambda- и Kappa-архитектуры. А то параллелизм числовых данных на GPU — это насколько узкая тема, что кроме учёных и любителей криптовалют, имхо, никому не интересна.
Так кривая ленивость — это тоже ошибка алгоритма, просто другого плана. Неведомой магии вообще в программировании не бывает, бывают неочевидные особенности )
Про Delphi — это тонкий троллинг или Вы до сих пор его в разработке используете?.. Честно говоря, ничего не знаю, про компонентно-ориентированное программирование или GUI на функциональных языках… Меня лично больше интересует область бэкенда для всяких веб- и mobile-приложений.
Скорость написания примерно такая же, как и на императивных языках, после того как осознаёшь функциональную парадигму и перестаёшь пытаться перетянуть туда императивные привычки.
И насколько углублённое знание лямбда-исчисления и прочей математики требуется чтобы писать быстро?
Просто не лезьте в Haskell и такие вещи как лямбда-исчисление, монады, функторы и т.д. Вас не потревожат )))
Т.е. ответ по существу — Вы можете вообще не знать что такое лямбда-исчисление и теория категорий, и прекрасно себя чувствовать на функциональных языках типа Elixir или Clojure, а также и на гибридных типа F#. Из ребусов только некоторые особенности записи могу вспомнить, но они скорее непривычные, чем сложные, и довольно легко осваиваются.
Когда Вы можете передать функцию в качестве параметра другой функции, или вернуть функцию из функции — это, безусловно, часть ФП, так как только в этой парадигме существуют функции высшего порядка.
Отвечу вместо nehaev… Использование ФП на 100% оправдано, когда вам нужна высококонкурентная программа с высокой степенью надежности и отказоустойчивости.
В таком случае вы либо будете использовать готовый ФЯП, либо переизобретёте большую часть ФП на своём любимом ЯП, либо будете страдать на каждом углу от race conditions, dead locks, гейзенбагов и прочих весёлых вещей.
А вот в императивных языках — как написал, так и работает.
Вы уверены, что это в императивных языках, а не в Ваших фантазиях? )
Откуда ж берутся null pointer exception, GIL и ещё 100500 подводных камней, когда работает совсем не так, как написал… Проблемы везде есть, и в императивных языках их совсем не мало. Но можно найти проблемы и в Прологе и в Хаскеле, тут никто не спорит. А если пытаться на них в императивном стиле программировать, то вообще феерический ппц будет, о чём и статья.
Ok, мутабельный, так мутабельный… Но это не отменяет того факта, что Вы сравниваете 2 совершенно разных алгоритма и удивляетесь, получив вполне ожидаемый результат. Чтобы сравнение было уместным, возьмите LinkedList добавьте в него строки через AddLast, а потом превратите в строку с помощью Join (желательно найти тот, который без лямбд). Хоть StringBuilder работает не так, но это по крайней мере алгоритмы одной сложности.
Сейчас клиенты пишут либо под браузер, либо под мобильники. И там и там можно использовать ФП, но на, мой взгляд, оно как раз больше для высоконагруженного сервера подходит. На клиентах выигрыш от ФП как-то неочевиден.
По определению, массив — структура данных, оптимизированная для произвольного доступа по индексу. Список — структура данных, оптимизированная для последовательного перебора.
А с точки зрения логики, если бы реализация этих структур принципиально не отличалась, то достаточно было бы одного названия )
Я умею работать с массивами, даже знаю пару алгоритмов на базе массивов. Где тут в вашем ФП массивы? Как нет? А что есть? А, списки… в моём любимом языке класс массива называется ArrayList, значит список — это типа массив такой. Сейчас как напрограммирую… Ой, а почему всё так тормозит? Как это нельзя к списку по индексу обращаться, вот же я обращаюсь и всё работает, тупит правда, но это потому что ФП медленный.
Странные у Вас примеры, честно говоря. Почему Вы противопоставляете StringBuilder и неизменяемые строки? StringBuilder — это просто удобная обёртка для работы с теми самыми неизменяемыми строками. Внутри он скорее всего хранит список этих самых строк, а при необходимости объединяет их в один проход. Другими словами, по сути StringBuilder такой же иммутабельный, как список в любом ФЯП.
На тему массивы vs списки — это ж вообще на уровне К.О. Если не понимать разницу между этими структурами данных, то очень легко писать тормозной код — это факт. По сути все проблемы от того, что некоторые программисты пытаются в силу инертности мышления работать с неизменяемыми структурами данных так, как-будто они изменяемые. Но из этого ничего хорошего не получится и как-то глупо в этом ФП обвинять, оно в инертности мышления не виновато )))
P.S. К.О. просит передать: Нельзя на базе списков реализовывать алгоритмы, предусматривающие доступ к элементам по индексу.
Это да. Просто в реальных ситуациях программа выполняет кучу действий, какие-то быстрее в функциональном подходе, какие-то — в императивном, и в среднем разница не особо велика.
+ не все задачи требуют «максимально быстро», бывает просто «достаточно быстро»
Например, разбор заголовка MP3-файла можно сделать декларативно, но если это надо сделать для 100500 файлов, то придётся вспомнить про fseek. Другими словами, инструмент зависит от задачи, и чем больше у вас инструментов, тем легче выбрать наиболее подходящий под конкретную задачу.
Дело даже не в затруднении реализации привычных алгоритмов, а в том, что при добавлении элемента в список, мне нужно создать целый новый список. А если он большой?
На практике это очень легко решается — хвост списка всегда переиспользуется под капотом, он же неизменяемый. Т.е. когда вы добавляете элемент в начало списка — это равнозначно смене указателя на голову списка, никакого копирования данных не происходит.
пользователю разумно ожидать, что какое-то действие программы будет выполняться, скажем минут за 5, а с нашими алгоритмами, оно выполняется за 30?
Вы в каких-то стереотипах живёте… С чего Вы взяли, что ФП само по себе что-то делает в разы медленнее… для реальных задач скорее будет 5 и 6, и то при условии, что 5 — это что-то из серии C/C++, D, Go, Rust.
Более того существуют интерпретируемые императивные ЯП, которые как раз в разы медленнее, компилируемых (в том числе и функциональных). И ничего, прекрасно себе существуют и куча применений им находится.
Насколько реально, для прикладных задач, строго сформулировать разумные ожидания пользователя? Как это вообще сделать? Кто должен этим заниматься, и сколько времени это займет?
Вообще, есть такая профессия, бизнес-аналитик называется. Впрочем, Вы там в сторону математического доказательства корректности углубились. Хотя по факту это не имеет смысла, достаточно того, что ФП упрощает то самое юнит-тестирование.
Другими словами, вопрос только в качестве, удобстве и полноте поддержки той или иной парадигмы в языке.
Я уже несколько раз тут в комметах писал… не надо пытаться реализовывать императивные алгоритмы в функциональном стиле. Ничего хорошего из этого не получится. И это ни разу не аргумент против ФП.
Мне вот интереснее применение ФП для таких проектов как WhatsApp, Twitter и т.д.
Про программирование на GPU я Вам не подскажу, т.к. не интересуюсь этой темой. Если Вы хотели подколоть на тему, что для параллелизма есть инструменты получше, то вспомнили бы лучше Lambda- и Kappa-архитектуры. А то параллелизм числовых данных на GPU — это насколько узкая тема, что кроме учёных и любителей криптовалют, имхо, никому не интересна.
Скорость написания примерно такая же, как и на императивных языках, после того как осознаёшь функциональную парадигму и перестаёшь пытаться перетянуть туда императивные привычки.
Просто не лезьте в Haskell и такие вещи как лямбда-исчисление, монады, функторы и т.д. Вас не потревожат )))
Т.е. ответ по существу — Вы можете вообще не знать что такое лямбда-исчисление и теория категорий, и прекрасно себя чувствовать на функциональных языках типа Elixir или Clojure, а также и на гибридных типа F#. Из ребусов только некоторые особенности записи могу вспомнить, но они скорее непривычные, чем сложные, и довольно легко осваиваются.
В таком случае вы либо будете использовать готовый ФЯП, либо переизобретёте большую часть ФП на своём любимом ЯП, либо будете страдать на каждом углу от race conditions, dead locks, гейзенбагов и прочих весёлых вещей.
Откуда ж берутся null pointer exception, GIL и ещё 100500 подводных камней, когда работает совсем не так, как написал… Проблемы везде есть, и в императивных языках их совсем не мало. Но можно найти проблемы и в Прологе и в Хаскеле, тут никто не спорит. А если пытаться на них в императивном стиле программировать, то вообще феерический ппц будет, о чём и статья.
А с точки зрения логики, если бы реализация этих структур принципиально не отличалась, то достаточно было бы одного названия )
На тему массивы vs списки — это ж вообще на уровне К.О. Если не понимать разницу между этими структурами данных, то очень легко писать тормозной код — это факт. По сути все проблемы от того, что некоторые программисты пытаются в силу инертности мышления работать с неизменяемыми структурами данных так, как-будто они изменяемые. Но из этого ничего хорошего не получится и как-то глупо в этом ФП обвинять, оно в инертности мышления не виновато )))
P.S. К.О. просит передать: Нельзя на базе списков реализовывать алгоритмы, предусматривающие доступ к элементам по индексу.
+ не все задачи требуют «максимально быстро», бывает просто «достаточно быстро»
Например, разбор заголовка MP3-файла можно сделать декларативно, но если это надо сделать для 100500 файлов, то придётся вспомнить про fseek. Другими словами, инструмент зависит от задачи, и чем больше у вас инструментов, тем легче выбрать наиболее подходящий под конкретную задачу.
«OOP means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things» © A.Kay
Поэтому практически значимые отличия ООП и ФП:
1) (Им-)мутабельность данных. В ФП данные неизменяемы, что затрудняет реализацию некоторых привычных алгоритмов, основанных на in-place модификации данных. Зато упрощает сборку мусора и конкурентный доступ.
2) Работа с разделяемым состоянием. ООП равномерно размазывает его по всей программе, попутно позорно нарушая инкапсуляцию при помощи геттеров и сеттеров. А ФП изолирует работу с разделяемым состоянием. И вместо блокировок использует очереди сообщений или STM.
Более того существуют интерпретируемые императивные ЯП, которые как раз в разы медленнее, компилируемых (в том числе и функциональных). И ничего, прекрасно себе существуют и куча применений им находится.
Вообще, есть такая профессия, бизнес-аналитик называется. Впрочем, Вы там в сторону математического доказательства корректности углубились. Хотя по факту это не имеет смысла, достаточно того, что ФП упрощает то самое юнит-тестирование.