Pull to refresh
4K+
12
Иван Курчин@divideme

User

5
Rating
4
Subscribers
Send message

Это каких, например? Наличие “оператора композиции”? Или вы о чём-то другом?

Я отразил своё мнение по этому поводу в статье, предметно, с примерами кода как на Scala так и на JS. То, что лично вас это не убеждает полностью ортогонально правдивости или ложности моей аргументации.

:-) Ну я весьма значительную часть своей карьеры провел за Erlang’ом… где - внезапно - из всего вами перечисленного - “из коробки” - есть только “изоляция эффектов”. И? Erlang - как ФЯП - недосягаем что для JS, что для Scala. Дальше-то что? Порассуждаем за “а насколько функционален Erlang?”, если в нем “всего этого” нет? :-)

Вы не отвечаете на мой вопрос: я не спрашивал вас о вашем карьерном пути в Erlang'e, я спрашивал: "как часто вы видите применение паттернов ФП (и, если вам угодно, "программирование в функциональном стиле") в проектах написанных на JavaScript?" В ответ на это вы приводите мне Erlang в качестве примера с аргументацией "там ничего из того, что вы перечислили - нет". И что это доказывает? Я вообще не могу понять, к чему вы это написали: естественно Эрланг функциональный язык, да, в нём отсутствуют из коробки некоторые перечисленные мною фичи, а еще там нет переменных, циклов и есть иммутабельность (и это, в том числе те признаки, что я указал в статье). Я нигде не писал, что в ФЯП должны присутствовать все пункты одновременно, более того: речь вообще шла исключительно о JS/TS. Вы упомянули, что в статье ничего не сказано про HOF. В ней ничего нет об этом потому, что в JS HOF есть, проблема в том, что на практике это никак не помогает, т.к. язык и его экосистема сподвигает вас писать циклы, сподвигает вас писать мутабельный код, сподвигает вас использовать что угодно кроме тайпклассов, сподвигает вас писать try/catch c мутациями внутри, сподвигает писать кругом проверки на null & undefined, и так далее, и всё это потому, что в этом языке так писать удобнее, эргономичнее и проще, а еще именно такие инструменты у вас имеются из коробки, а код в большинстве случаев хоть и менее безопасный но более читабельный и привычный для комьюнити и разработчиков. Да, в Эрланг у вас может не быть HKT, но и цикл вы не напишите.

А причем тут “функциональная чистота”, и система типов?! “Чистота”, она как раз в гораздо большей степени про модель вычислений, чем про что-то другое. Нет?

Я нигде и не утверждал обратного, вы за меня додумываете. Если бы у вас был опыт написания строготипизированного кода в функциональном стиле на TS, то вы бы знали, какой эквилибристикой порой приходится заниматься, чтобы ваши типы "сошлись" и чтобы TS вас верно понял. Особенно когда речь касается типизации функций высшего порядка. Откройте source fp-ts и посмотрите, как они определяют функцию pipe, например.

С какого перепугу-то?!

С такого. У вас нарушается принцип "подстановки" (substitution) и это ломает композицию. Как минимум, вы получаете строгую зависимость от порядка вычислений.

Пока что из всей дискуссии я так и не понял, что конкретно делает Erlang "недосягаемым ФЯП" в рамках вашего определения через HOF в системе типов. А в местах, где должен идти аргумент вы просто вставляете ":-)". Не говоря о том, что часть вашего текста - это ваше оценочные суждения поданные в императивной и назидательной нотации без какого-либо раскрытия и доказательства. Вы либо приводите аргумент полностью, от и до, без намёков и пространных суждений, либо не приводите его вовсе, а то мне приходится заниматься дешифровкой ваших сообщений.

Да, вчера уже была обнаружена эта ошибка, меня поглотила тьма, когда я это писал. Этот кусок удален, текст скорректирован!

Спасибо вам огромное, что заметили эту жесть)) Писал этот кусок глубокой ночью, то ли в каких-то более старых версиях ТS была эта проблема (но даже если и была, то выглядела совсем не так, как я ее описал), то ли я ее сам "выдумал". Весь этот кусок удалил, ваше замечание полностью по делу, спасибо еще раз!

Ну так и есть. JS функционален ровно в той же степени, в которой функциональна, например, scala. Ибо функциональность - это не про модель вычислений (декларативность/императивность), не про стратегию вычислений (упрощая, ленивость/энергичность) и не про ещё кучу аспектов.

Функциональность - это про вполне определенное свойство системы типов.

Другое дело, что можно начать рассуждать о - так сказать - “чистоте” этой функциональности… :-)

На мой взгляд вы очень сильно упрощаете. И ваша последняя строчка, где вы как бы "забираете" часть своего аргумента назад - прямое тому подтверждение. JS даже не рядом со Scala в вопросах "функциональности", ни на каком из уровней. Плотность и эргономика функциональных фич в Scala на порядки выше, а систему типов и сравнивать смешно.

?! В Erlang замечательная система типов. С чего вы взяли, что её (системы типов) там нет?!

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

Мой поинт-то в том, что не понятно, какое отношение наличие/отсутствие ссылочной прозрачности имеет к функциональности ЯП?

В узком смысле слова вы правы: СП - это свойство выражения, а не языка. Но проблема в том, что то, что не ссылочно-прозрачно крайне плохо композируется. Если нет функциональной композции и / или она ограниченна, то писать функциональный код становится проблематично и больно.

Можно долго спорить о терминологии, но факт в том, что культура написания кода на разных языках формируется не только на основании спецификаций и систем типов, но еще и в практическо-прагматической среде. Приживается то, что более естественно для конкретного языка, что более удобно для решения задач, под которые этот язык подходит. И на мой взгляд это куда важнее, чем то, о чём вы говорите выше. Я к тому, что ставить == между языками с точки зрения "функциональности" основываясь только на том, что система типов знает про HOF - это очень сильное упрощение, которое полностью оторванно от реальной практики применения языков: сколько вы лично видели проектов в продакшене на JS, где активно используется карирование, частичное применение, монады, изоляция эффектов(то, что для вас всё это не является критерием фп - и я хочу это подчеркнуть двумя толстыми линиями - это ваше личное оценочное суждение а не научный консенсус)? В то же время чисто функциональную Scala я вижу регулярно, в особенности после роста популярности Cats Effect и Zio

Я очень со многим из того, что вы пишите согласен.

По мне главные критерии ФП языка - это все-таки неизменяемость из коробки и логика языка в которой программа строиться вокруг функции как основного юнита.

В одной из книг про Cats Effect читал такое определение:

ФП - это локальное рассуждение(local reasoning) и композиция, всё остальное есть производные этих двух.

Вспомнил его, когда читал ваш пост, показалось довольно созвучным.

Взять Scala, там исключений нет или есть мутабельность по умолчанию? Да там половина языка Java подобна, о чем говорить.

Согласен, но с одним на мой взгляд важным уточнением: в Scala последние несколько лет укоренилась тенденция создания эффектных систем (Cats Effect, Zio), что очень сильно "качнуло" маятник в сторону чистого функционального программирования.Т.е. да, в языке действительно ярко выраженная мультипарадигмальность, но на практике эта дихотомия сегодня ощутимо менее выражена, если сравнивать с периодом популярности Akka, например.

Понятно что JS - это не ФП язык. Но не нужно все мерить по Haskell. JS/TS в такой ситуации, что разумная доля ФП подхода без перебора пока что дает сильно больше преимуществ чем другие подходы. Вопрос лишь в адекватных рамках этого.

Вот это, и то, что вы пишите касательно Haskell-like языков - довольно интересный тейк в том смысле, что ведь действительно в мире программирования есть такие... "Маппинги" вроде "Мы говорим ООП, подразумеваем - Java", мы говорим "FP, подразумеваем - Haskell", но довольно серьезный вопрос в том, насколько корректны подобные "маппинги" в принципе.

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

Я утверждал обратное — что мутабельность по умолчанию ссылочную прозрачность нарушает, а не что иммутабельность её гарантирует, это разные тезисы.

Про конфликт TCO и ленивости — не очень понял тезис. Haskell ленивый, но TCO там есть и используется. Проблема стека трансформируется в space leaks, но не исчезает совсем. Если имеется в виду что они решают разные проблемы — согласен, но это скорее ортогональность, чем конфликт.

Касательно try/catch и Erlang: конкретно тут он ни при чём, в том блоке я разбирал try/catch в JS, и там это является инструкцией, а не выражением. И это не моё мнение, а факт.

Имманентный свойством ФЯП (любого - без каких-либо исключений) является исключительно система типов, которая умеет в HOF (а у вас про них вообще нет ничего). Другими словами - без наличия в системе типов функций высшего порядка - ФЯП не бывает.

Интересное определение, но оно ломается на примере, который вы сами привели — Erlang динамически типизирован, никакой системы типов с HOF там нет. Тем не менее функциональным языком он считается.

Если вы имели в виду просто сам факт того, что для ФП необходимо иметь возможность писать HOF - то с этим глупо спорить, всё так. Моя проблема с формулировкой в том, что Если HOF — единственный(или основной) критерий, то JS функциональный язык, it's simple as that.

Про HKT и PM - вы, похоже, не понимаете место этих концепций в ЯП (любом).

Звучит как ваше оценочное суждение без каких-либо оснований.

Я не утверждал, что функтор - это HKT. Я пытался на простом примере показать механизм системы типов, который позволяет выразить тайпкласс (т. е. что функтор параметризован HKT)

Впервые слышу, чтобы JS называли функциональным

Этот тезис «кочует» по страницам книг, звучит в публичных выступлениях, есть даже целые курсы, в т.ч. от крупных и известных платформ вроде «frontend masters» где это мнение присутствует, так же я сослался на свой личный опыт проведения интервью. Я к тому, что у нас с вами опыт может сильно отличаться и это вполне нормально. В то же время то, что вы не слышали тезис «JS - функциональный язык» не означает, что этого тезиса не существует.

То поверху, то понизу - если вы хотите ФП на JS, по каким либо причинам вместо clojurescript или другого вообще стека, то это нормальные либы. Костыли или нет, это уже, что-то на снобском

Всё это - ваше личное оценочное суждение, не более. Никакого снобизма тут не было: я лишь констатировал факт того, что «из коробки» в языке решений не существует, требуется использование дополнительных инструментов. Некоторые из них абсолютно гениальные(effect ts, fp-ts), некоторые, на мой взгляд, менее удачные.

Effect-ts в продакшене попробовать не довелось, а вот с fp-ts поработал на двух проектах.

На мой взгляд, библиотека очень мощная, но с онбордингом возникали определенные сложности. Если люди прежде не писали на функциональных языках, код на fp-ts для них выглядит тяжеловесно. И местами, надо признать, это ощущение вполне заслуженно — порог входа высокий и код визуально кажется совсем "чужим", не похожим на привычный TS.

Кроме того, есть сугубо практический нюанс интеграции. Допустим, мы пишем React-приложение. Подключаем React Query, которая, естественно, ничего не знает про монады Task / TaskEither. Приходится писать адаптеры, превращающие ТЕ обратно в обычные Promise. Да, это пара строк кода, но React Query — не единственная такая библиотека. Любой хук форм или роутер заставляет держать в голове эти пограничные прослойки.

В итоге появляется постоянный оверхед (пусть и небольшой), оправданность которого в команде — вопрос дискуссионный. Лично я считал, что строгость типов и обработка ошибок того стоят, кто-то другой скажет, что нет. Собственно, это прямое продолжение того, что я в статье назвал «гравитацией языка» — экосистема постоянно тянет тебя обратно в императивный мир.

По Haskell абсолютно справедливое замечание, стоило быть точнее. С одним лишь важным нюансом: насколько я знаю, Haskell "культурно поощряет" именно стиль с использованием Either / Maybe монад.

По ОCaml и HKT - супер важное уточнение. В таком случае отсутствие HKT - это больше ограничение выразительности при написании обобщённых абстракций, а не маркер "функциональности" языка как таковой. Поправлю формулировку, спасибо!

Да, это рабочий паттерн и важное уточнение, спасибо — мне стоило про это упомянуть. Но то, что я сам про это забыл, лишний раз доказывает тезис: язык мне здесь не помогает, это просто соглашение, которое нужно держать в голове и применять в каждом switch вручную.

Ну и проблему открытой иерархии это, к сожалению, не решает.

Information

Rating
1,064-th
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Date of birth
Registered
Activity

Specialization

Фулстек разработчик
Ведущий
JavaScript
HTML
CSS
React
Scala
TypeScript
Vite
Адаптивная верстка
Кроссбраузерная верстка
Next.js