Ложь о “first-class functions”

Viktor Love
3 min readAug 28, 2018

--

Комментарий: это спекулятивная статья, которая ставит вопрос, но не дает ответа.

Нынче очень многие языки пиарят себя как языки, которые считают функции равноправными с объектами и примитивами типа чисел.

Ложь, вранье и провокация!

Строго говоря, это не совсем ложь. Концепция “объект первого класса” имеет строгое определение (описано в ссылке), которому следуют большинство языков. Но само определение не описывает кучу других прикольных вещей, которые можно делать с объектами.

Все следуют букве закона, но не духу закона! Идеальное равноправие — вот наша мечта!

В чем проблема?

Рано или поздно вы встречаетесь с тем, что ранее работавшие подходы перестают работать в слегка новых условиях.

И ладно бы причина была, а так — огребаем на ровном месте. Как будто кто-то специально хочет подтвердить фразу “серебряной пули нет”.

В целом мы получаем протекающую абстракцию. Приходится постоянно помнить, что нельзя всегда трактовать функции как данные.

Замыкание — это данные

Это важно!

Можно легко написать лисп-интерпретатор. После такого трюка все функции (замыкания) превращаются в данные. Просто с ними будет неудобно работать как с обычными функциями.

Любое рассуждение строго отделяющее функции от данных не имеет смысла. Разве что вы под данными подразумеваете какое-то убожество.

Да, мало кто в здравом уме будет писать свой интерпретатор и читать код из недоверенного источника.

Прим.: а статистически разница между функциями и типичными данными все-таки будет.

Равенство функций

Объекты можно проверять на равенство как угодно. Хочешь написать кастомную функцию проверки равенства — да пожалуйста. Увы, функции можно сравнивать только в рамках концепции “ссылочного равенства”.

Представьте, что мы из какой-то функции возвращаем данные:

func getData() {
return { field1: 1, field2: "2" }
}

Добавим еще какую-нибудь функцию в поле объекта:

func getData() {
return { field1: 1, field2: "2", field3: () => 3 }
}

Ломаются:

  • кеширование (объект уже нельзя использовать как ключ словаря)
  • трекинг изменений (уже нельзя сказать, что вызовы getData возвращают эквивалентные данные)

Прим.: математическая эквивалентность функций не имеет к сабжу никакого отношения

Сериализация

Функции часто невозможно сериализовать. Драма та же.

Если у вас есть данные, которые вы хотите где-то сохранять, то ни в коем случае нельзя допускать появления функций в данных.

Ладно бы проблема была в том, что трудно обеспечить сохранение/восстановление функций. Всегда можно придумать способ, позволяющий это делать в вашем конкретном случае.

Но это попросту невозможно без грязных трюков. Потому что запретили.

Прим.: вот няшный кейс: логирование и воспроизведение.

IPC/сеть

Многие умственно отсталые люди делают границы систем через процессы/очереди/микросервисы. Иногда это оправданно.

Из-за невозможности сериализовать функции мы не можем использовать ФП между системами.

И это аукается. Приходится писать кучу баллшита. Мне особенно доставляют сценарии “постоим 100мс для вычисления, которое можно сделать в одном месте”.

Прим.: да, зачастую это вопрос не одного языка

Вопросы безопасности

Я встречал аргументацию о том, что исполнение функций из черт знает откуда — это плохо. Да, так и есть.

Использовать данные из черт знает откуда — это тоже плохо. Но не так сильно аукается. До поры до времени. Чем-то похоже на "security through obscurity".

Нельзя полагаться на то, что подмененные данные менее вредны, чем подмененный код. Это попытка жить только сегодняшним днем. В будущем новенький разработчик может забыть (или вовсе не знать), что источник данных не безопасен. И может легко родить уязвимость.

Да, в unmanaged языках это приводит к действительно дерьмовым последствиям вроде выдачи любых данных из памяти. В managed языках эти проблемы более редки, но все ещё остается огромное количество векторов атаки.

Отвалидированная функция из доверенного источника не представляет опасности.

Наплевательское отношение к безопасности “просто данных” вам пользы не принесёт.

О чем это я

Полюбите ФП всеми фибрами души, иначе вы будете гореть в аду за пропаганду убогого стиля программирования.

Честно говоря, я не знаю что полезного можно сделать. Поэтому и буду дальше писать в спортлото.

Прим.: под убогим стилем программирования ваш покорный пиздабол подразумевает отсутствие мультипарадигменности.

Прим.: автор ни в коем случае не имел в виду, что ад существует. Автор глубоко сожалеет о том, что его возможно нет.

--

--

Viktor Love
Viktor Love

Written by Viktor Love

Software Engineer from Ukraine. TypeScript, React, C#, Angular.

Responses (1)