Вывод не верен в принципе, независимо от истинности/ложности предпосылок. Каждый язык имеет ограничения, но из этого не следует, что этот язык ущербен. Ограничение может быть достоинством языка.
пользователь процедурного языка, как правило, имеет возможность писать функциональный подход
отсутствие АТД.
отсутствие нужных (для ФП) функций и структур данных в системных библиотеках.
громоздкий синтаксис для функциональных конструкций, снижающий выразительность (читабельность).
Эти и другие причины зачастую не позволяют использовать функциональный стиль. как следует.
пользователь функционального языка, как правило, жёстко ограничен функциональными рамками
Наоборот. Пользователь функционального языка, как правило, не ограничен функциональными рамками. Единственный язык с жёстким ограничением, про который я слышал, это Haskell (но это не является недостатком Haskell).
споткнется лиспер, пытаясь разобраться в том, занахрена тут доллар и что значит snd
Я вот знаю, JS, C#, C++. И при этом не могу понять, что в Вашем коде значит "my ($n) = @_;"
Любой, кто изучает Haskell, довольно быстро выучит стандартные операторы. Тем более, что их меньше, чем ключевых слов в C#/C++.
И, кстати, оператор $ всегда можно заменить на скобки. Но с $ читабельность повышается. А вот с C#/C++ нет альтернативы вложенным скобкам (разве что вводить переменные для части выражения).
Ахиллес не догонит черепаху за заданное ((в виде частичной суммы) в условии время. Это время меньше, чем требуется Ахиллесу, чтобы догнать черепаху. В чём парадокс?
И я не верю, что древние греки были настолько тупы, чтобы не понимать этого. Тот же ряд 1/2 + 1/4 + 1/8 + 1/16 + ... слишком очевидно даёт конечную сумму, сколько его не считай.
Понимали. Потому что у этого ряда есть чёткая геометрическая интерпретация: делим прямоугольник ("единицу") пополам, половину - ещё пополам, ... и так далее. В сумме получим площадь не больше исходного прямоугольника (на любом этапе "деления")..
итерате, это, извините проникновение процедурного стиля в язык сектантов.
iterate - это обычная функция с простым кодом
iterate f x = x : iterate f (f x)
Это не проникновение процедурного стиля в функциональный, а классический пример выделения абстракции. Выделение абстракций для алгоритмов - характерная черта для функциональных языков.
Конечно, код можно было записать и без использования этой функции:
fib n = snd $ f (1,0) n
where
f x 0 = x
f (a,b) n = f (a+b, a) (n-1)
Но писать свою функцию, когда есть библиотечная, плохо.
если более выразительный код имеет смысл только как демонстрация
Конечно, нет. Более выразительный код имеет смысл, потому что его проще поддерживать и дорабатывать. Так уж получается, что программисты больше читают код, чем пишут.
только мемоизация куда менее выразительна, нежели обычный цикл с парой переменных,
Наоборот.
В динамическом программировании часто бывает так. Сходу можно записать очевидный (более понятный) алгоритм, использующий древовидный рекурсивный процесс. А потом, после некоторых раздумий его удаётся переписать на менее выразительный, но более эффективный линейный итеративный процесс.
Более выразительный код - значит проще понять, что этот код делает (какую задачу решает).
В функциональном стиле тоже можно использовать такой алгоритм и получить сложность O(N). А можно использовать более эффективный алгоритм и получить сложность O(logN).
ещё раз: программирование ряда Фибоначчи - эталонное "не нужно".
Я Вам привёл простейший код с древовидной рекурсией. Мог привести, например, обход в глубину.
fib(fib(fib(fib(fib(fib(fib(fib(
По Вашей схеме функция fib принимает результат (одного) вызова функции fib, то есть, некое (одно) число Фибоначчи. Это неверно для приведённого мной кода. Но такое будет возможно, если (переписать fib) заменить рекурсивный вычислительный процесс на итеративный.
Сможете переписать программу, чтоб дважды не вычислялись эти числа?
Да. Существует несколько способов это сделать. Например, добавить мемоизацию.
никакая реализация SQL не сделает, например, JOIN над TREE-выборками дешевле сложности O(N * log N)
При наличии индексов это неверно, но не суть. Суть в том, что код на SQL будет выразительней (понятней читателю), чем код на Си, который делает то же самое. Поэтому "функциональный" (на самом деле - декларативный) SQL для подобных задач лучше, чем императивный Си.
если человек, нанимающийся на работу, не знает и не хочет знать о таких нюансах, то он не доработает и до конца испытательного срока.
То, что происходит "под капотом", зависит не от языка, а от конкретной реализации языка и от архитектуры конкретной системы. На выразительность языка это никак не влияет.
недаром рядом с SQL каждая уважающая себя БД даёт возможность использовать PL/SQL. Почему? А потому что часто процедурный стиль куда более выразительный.
Не поэтому.T-SQL используется для решения задач, для которых SQL не предназначен. Причём, из-за невыразительности T-SQL эту часть предпочитают вынести в код на основном языке (в моём случае C#), если это не противоречит требованиям (к оформлению и производительности).
часто процедурный стиль куда более выразительный.
Даже простой SQL запрос "select name from table where id = 123" выглядит выразительней (понятней), чем цикл, который делает то же самое. А если добавить join, то разница будет ещё больше.
По использованию памяти разницы нет, так как при хвостовом вызове место в стеке, выделенное для вызывающей функции, уже не нужно. Всё, что требуется, это использовать адрес возврата.вызывающей функции в качестве адреса возврата вызываемой функции.
Вывод не верен в принципе, независимо от истинности/ложности предпосылок. Каждый язык имеет ограничения, но из этого не следует, что этот язык ущербен. Ограничение может быть достоинством языка.
отсутствие АТД.
отсутствие нужных (для ФП) функций и структур данных в системных библиотеках.
громоздкий синтаксис для функциональных конструкций, снижающий выразительность (читабельность).
Эти и другие причины зачастую не позволяют использовать функциональный стиль. как следует.
Наоборот. Пользователь функционального языка, как правило, не ограничен функциональными рамками. Единственный язык с жёстким ограничением, про который я слышал, это Haskell (но это не является недостатком Haskell).
Я вот знаю, JS, C#, C++. И при этом не могу понять, что в Вашем коде значит "
my ($n) = @_;"Любой, кто изучает Haskell, довольно быстро выучит стандартные операторы. Тем более, что их меньше, чем ключевых слов в C#/C++.
И, кстати, оператор $ всегда можно заменить на скобки. Но с $ читабельность повышается. А вот с C#/C++ нет альтернативы вложенным скобкам (разве что вводить переменные для части выражения).
Не обманывайте. Напоминаю, моей целью было не написать вычисление чисел Фибоначчи, а предоставить Вам пример древовидного рекурсивного процесса.
Всё остальное тоже неверно, на что я Вам уже указывал. Поэтому комментировать не буду.
Ну так используйте. Чего стоит Ваш перл или любой другой язык без системных библиотек?
Это операторы. Вы тоже используете операторы (например, плюс).
Без системных функций в две, а не в четыре.
Если Вы забыли, то напомню:
У меня получилась одна строка.
Если Вы забыли, напомню:
Из неверных утверждений Вы получили неверный вывод. Ничего удивительного.
Ахиллес не догонит черепаху за заданное ((в виде частичной суммы) в условии время. Это время меньше, чем требуется Ахиллесу, чтобы догнать черепаху. В чём парадокс?
Понимали. Потому что у этого ряда есть чёткая геометрическая интерпретация: делим прямоугольник ("единицу") пополам, половину - ещё пополам, ... и так далее. В сумме получим площадь не больше исходного прямоугольника (на любом этапе "деления")..
iterate - это обычная функция с простым кодом
Это не проникновение процедурного стиля в функциональный, а классический пример выделения абстракции. Выделение абстракций для алгоритмов - характерная черта для функциональных языков.
Конечно, код можно было записать и без использования этой функции:
Но писать свою функцию, когда есть библиотечная, плохо.
Простая хвостовая рекурсия задаёт линейный итеративный процесс. Но и это не конвейер, так как число итераций заранее неизвестно.
Пример конвейера:
или (то же самое)
В Вашем представлении любая программа на Си является конвейером.
Конечно, нет. Более выразительный код имеет смысл, потому что его проще поддерживать и дорабатывать. Так уж получается, что программисты больше читают код, чем пишут.
У меня получилось именно то, чего я хотел - предоставить Вам пример древовидного рекурсивного процесса.
А вычисление чисел Фибоначчи за O(N) сложности не представляет:
сравните выразительность императивного и функционального стилей.
Императивный: Устанавливаем Счётчик в 0. Выполняем Действие и увеличиваем Счётчик на 1, пока Счётчик меньше N.
Функциональный: Выполняем Действие N раз.
Нет.
Конвейер: f(g(h(x)))
Не конвейер f(g(x) + h(y))
Наоборот.
В динамическом программировании часто бывает так. Сходу можно записать очевидный (более понятный) алгоритм, использующий древовидный рекурсивный процесс. А потом, после некоторых раздумий его удаётся переписать на менее выразительный, но более эффективный линейный итеративный процесс.
Более выразительный код - значит проще понять, что этот код делает (какую задачу решает).
В функциональном стиле тоже можно использовать такой алгоритм и получить сложность O(N). А можно использовать более эффективный алгоритм и получить сложность O(logN).
Нет. Эта сложность - плата за выбранный алгоритм.
Я Вам привёл простейший код с древовидной рекурсией. Мог привести, например, обход в глубину.
По Вашей схеме функция fib принимает результат (одного) вызова функции fib, то есть, некое (одно) число Фибоначчи. Это неверно для приведённого мной кода. Но такое будет возможно, если (переписать fib) заменить рекурсивный вычислительный процесс на итеративный.
Да. Существует несколько способов это сделать. Например, добавить мемоизацию.
При наличии индексов это неверно, но не суть. Суть в том, что код на SQL будет выразительней (понятней читателю), чем код на Си, который делает то же самое. Поэтому "функциональный" (на самом деле - декларативный) SQL для подобных задач лучше, чем императивный Си.
То, что происходит "под капотом", зависит не от языка, а от конкретной реализации языка и от архитектуры конкретной системы. На выразительность языка это никак не влияет.
Не поэтому.T-SQL используется для решения задач, для которых SQL не предназначен. Причём, из-за невыразительности T-SQL эту часть предпочитают вынести в код на основном языке (в моём случае C#), если это не противоречит требованиям (к оформлению и производительности).
Даже простой SQL запрос "select name from table where id = 123" выглядит выразительней (понятней), чем цикл, который делает то же самое. А если добавить join, то разница будет ещё больше.
По использованию памяти разницы нет, так как при хвостовом вызове место в стеке, выделенное для вызывающей функции, уже не нужно. Всё, что требуется, это использовать адрес возврата.вызывающей функции в качестве адреса возврата вызываемой функции.
запишите в виде пайплайна