Ложь о “first-class functions”
Комментарий: это спекулятивная статья, которая ставит вопрос, но не дает ответа.
Нынче очень многие языки пиарят себя как языки, которые считают функции равноправными с объектами и примитивами типа чисел.
Ложь, вранье и провокация!
Строго говоря, это не совсем ложь. Концепция “объект первого класса” имеет строгое определение (описано в ссылке), которому следуют большинство языков. Но само определение не описывает кучу других прикольных вещей, которые можно делать с объектами.
Все следуют букве закона, но не духу закона! Идеальное равноправие — вот наша мечта!
В чем проблема?
Рано или поздно вы встречаетесь с тем, что ранее работавшие подходы перестают работать в слегка новых условиях.
И ладно бы причина была, а так — огребаем на ровном месте. Как будто кто-то специально хочет подтвердить фразу “серебряной пули нет”.
В целом мы получаем протекающую абстракцию. Приходится постоянно помнить, что нельзя всегда трактовать функции как данные.
Замыкание — это данные
Это важно!
Можно легко написать лисп-интерпретатор. После такого трюка все функции (замыкания) превращаются в данные. Просто с ними будет неудобно работать как с обычными функциями.
Любое рассуждение строго отделяющее функции от данных не имеет смысла. Разве что вы под данными подразумеваете какое-то убожество.
Да, мало кто в здравом уме будет писать свой интерпретатор и читать код из недоверенного источника.
Прим.: а статистически разница между функциями и типичными данными все-таки будет.
Равенство функций
Объекты можно проверять на равенство как угодно. Хочешь написать кастомную функцию проверки равенства — да пожалуйста. Увы, функции можно сравнивать только в рамках концепции “ссылочного равенства”.
Представьте, что мы из какой-то функции возвращаем данные:
func getData() {
return { field1: 1, field2: "2" }
}
Добавим еще какую-нибудь функцию в поле объекта:
func getData() {
return { field1: 1, field2: "2", field3: () => 3 }
}
Ломаются:
- кеширование (объект уже нельзя использовать как ключ словаря)
- трекинг изменений (уже нельзя сказать, что вызовы getData возвращают эквивалентные данные)
Прим.: математическая эквивалентность функций не имеет к сабжу никакого отношения
Сериализация
Функции часто невозможно сериализовать. Драма та же.
Если у вас есть данные, которые вы хотите где-то сохранять, то ни в коем случае нельзя допускать появления функций в данных.
Ладно бы проблема была в том, что трудно обеспечить сохранение/восстановление функций. Всегда можно придумать способ, позволяющий это делать в вашем конкретном случае.
Но это попросту невозможно без грязных трюков. Потому что запретили.
Прим.: вот няшный кейс: логирование и воспроизведение.
IPC/сеть
Многие умственно отсталые люди делают границы систем через процессы/очереди/микросервисы. Иногда это оправданно.
Из-за невозможности сериализовать функции мы не можем использовать ФП между системами.
И это аукается. Приходится писать кучу баллшита. Мне особенно доставляют сценарии “постоим 100мс для вычисления, которое можно сделать в одном месте”.
Прим.: да, зачастую это вопрос не одного языка
Вопросы безопасности
Я встречал аргументацию о том, что исполнение функций из черт знает откуда — это плохо. Да, так и есть.
Использовать данные из черт знает откуда — это тоже плохо. Но не так сильно аукается. До поры до времени. Чем-то похоже на "security through obscurity".
Нельзя полагаться на то, что подмененные данные менее вредны, чем подмененный код. Это попытка жить только сегодняшним днем. В будущем новенький разработчик может забыть (или вовсе не знать), что источник данных не безопасен. И может легко родить уязвимость.
Да, в unmanaged языках это приводит к действительно дерьмовым последствиям вроде выдачи любых данных из памяти. В managed языках эти проблемы более редки, но все ещё остается огромное количество векторов атаки.
Отвалидированная функция из доверенного источника не представляет опасности.
Наплевательское отношение к безопасности “просто данных” вам пользы не принесёт.
О чем это я
Полюбите ФП всеми фибрами души, иначе вы будете гореть в аду за пропаганду убогого стиля программирования.
Честно говоря, я не знаю что полезного можно сделать. Поэтому и буду дальше писать в спортлото.
Прим.: под убогим стилем программирования ваш покорный пиздабол подразумевает отсутствие мультипарадигменности.
Прим.: автор ни в коем случае не имел в виду, что ад существует. Автор глубоко сожалеет о том, что его возможно нет.