Как стать автором
Обновить

Комментарии 161

SICP может быть несколько сложным для начала. Можно начать с "How to Design Programs, second edition: An Introduction to Programming and Computing", в русском переводе: "Как проектировать программы. Введение в программирование и компьютерные вычисления".

Эта книга может вам пригодиться только если вы станете попаданием в год эдак 1986. Тогда описанные там знания станут для вас очень актуальны.

спасибо за ссылку на русскоязычную книжку

PS: а каждый язык силён прежде всего инфраструктурой включения наработок на нём в CI/CD.

То есть первое, куда стоит смотреть, это "как на этом языке писать интеграционные и юниттесты", ну и как со всем этим вылезать в прод.

А как на схеме/лисп принято код тестировать?

С точки зрения CI/CD интерпретируемый язык вроде Lisp или Scheme очень удобен, потому что можно менять код программы прямо по ходу её выполнения, не перезапуская её. А функциональный стиль подразумевает, что каждая отдельная функция – сама себе юнит, который можно тестировать, причём в нормальном случае она не имеет побочных эффектов. Поэтому сама постановка вопроса об отдельных юнит-тестах скорее является артефактом императивных языков.

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

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

я так и не понял: так таки да или так таки нет?

Что да или нет?

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

Если программировать на Scheme символьный ИИ, что на каком-нибудь C++ вообще малореально, то тестирование затруднено, потому что сама фишка любого ИИ в том, что его невозможно покрыть тестами.

Обычно на Scheme хорошо программировать такие приложения, которые вообще не имеют никакой определённой прикладной логики в момент запуска, а являются некой конфигурируемой пользователем средой.

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

Не думаю, что дело в интеллекте. Скорее, в привычности и насмотреннности, плюс в поддержке более мейнстримных языков их сообществами и компаниями.

многие языки делает не столько сам язык, сколько образованная вокруг него инфраструктура.

Вот, например я беру в руки Rust ну или JS. Задаю вопрос:

  • как мне создать проект? сразу получаю документ о cargo или npm

  • как мне тестировать проект? получаю следующий документ

  • где мне искать написанные кем-то библиотеки? получаю третий документ

и так далее и тому подобное.

Rust силён не столько системой управления памятью, сколько https://crates.io/.

Как-то так.

Герои требуются там, где всей этой инфраструктуры нет.

Вы сейчас говорите о технологической оснастке для рабочего. А языки ФП - это больше инструменты для инженера-исследователя.

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

я сейчас говорю о причинах столь малой популярности языков ФП.

задача: "я хочу взять готовую библиотеку работы с БД MySQL и применить её в своей программе".

как я решаю её на Rust? Я пишу в командной строке

$ cargo search mysql

Как я буду решать её на Lisp/Scheme?

я пойду гуглить в интернет. и что важно, скорее всего не найду искомого (для mysql может что и найдётся, но для 9/10 поисков - нет)

А языки ФП - это больше инструменты для инженера-исследователя.

не очень понимаю, почему ФП подходит исследователю лучше, чем не ФП.

Исследователь он что делает? Ну например пытается "зрением" некоего робота оснастить. В этом месте помимо самого "зрения" он решает кучу (КУЧУ!) попутных задач и задача вроде "положить результаты измерения в БД" становится "проходной", "попутной" итп

Когда задача доходит до такого уровня понятности, что её можно решить типовым проектом на расте, её совершенно незачем программировать на Scheme.

То есть инженер-исследователь, потратив полгода-год на написание кода на LISP, получив положительный результат, начинает переписывать всё на Rust? А зачем ему LISP на стартовом этапе?

Необязательно разные задачи программировать на одном языке. И даже вредно.

Если говорить про зрение робота, то вкорячивать в его код интерфейс к конкретной СУБД – в любом случае плохое решение.

интерфейс к конкретной СУБД – в любом случае плохое решение.

то есть задачи стейтфул обработки данных для LISP не подходят?

только стейтлесс?

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

Во-вторых, желательно выбирать соответствующий задаче уровень абстракции. Где-то там внизу данные может хранить та или иная СУБД, но для алгоритма машинного зрения это точно неважно.

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

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

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

Чуть ли не все самообучающиеся алгоритмы на этом построены.

А потому задача "сохранить/загрузить данные в/из (БД/сети/диске/где-то)" - ну, чуть ли не рядовая.

Вопрос сохранения данных вообще, конечно, рядовой. Scheme в этом отношении, между прочим – удобный язык, так как не имеет проблем с сериализацией объектов. Но сохранение вообще не означает, что нужно тащить в высокоуровневый код API СУБД.

Но сохранение вообще не означает, что нужно тащить в высокоуровневый код API СУБД.

что такое СУБД?

это такая хрень, которая

  • готова (сделана не нами)

  • умеет масштабироваться

  • предназначена для разнообразнейших поисков по сохранённым данным

  • храня данные БД (против хранения в переменных языка) мы получаем условно-бесплатный способ интроспекции состояния, а ещё способ воздействия на это состояние

соответственно коннектор к API СУБД может понадобиться в любом более-менее сложном приложении.

  1. Коннектор – не означает само API СУБД.

  2. В большинстве случаев, когда в реальной жизни используются простые СУБД вроде mysql, аналогичных результатов можно достичь в Scheme более простым путём – через ассоциативные списки и функции высшего порядка. Ещё и быстрее будет из-за отсутствия потерь на коннект. Конечно, это не относится к высоконагруженным и огромным по размеру базам данных, но там вообще совершенно своя специфика работы.

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

Они запрещают состояния. Но компьютер (и любая другая машина Тьюринга) и есть машина состояний. Пишем мы на жёсткий диск, выводим на экран, получаем запрос по сети, посылаем ответ - всё это состояния.

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

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

Однако, на то же самое можно взглянуть с другой стороны: когда мы занимаемся какими-то формальными преобразованиями кода, например, оптимизацией, распараллеливанием, доказательством правильности – то состояния нам мешают.

НЛО прилетело и опубликовало эту надпись здесь

А что такое закозельская кукарямба?

НЛО прилетело и опубликовало эту надпись здесь

К сожалению, мне нет дела до того, какие слова или выражения вы выучили. Будь то "монада", "эндофунктор", "аорист" или "закозельская кукарямба".

Если бы это было важно - это бы нашло применение где-то за пределами случайных проектов в случайных компаниях и академических исследований о заведении лямбды за сигму.

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

Это применяется для написания компиляторов? Каких компиляторов? Как выясняется, это компиляторы из одного диалекта LISP в другой диалект LISP, описанные в мощнейшем университетском курсе 40-летней давности.

Это позволяет писать программы без ошибок? Как выясняется, под программой понимается не приложение, а кусок кода, который ничего не делает или считает ряд Фибонночи.

Это позволяет писать код яснее и короче? Приведённые примеры - что-то инопланетное, из них вообще невозможно понять, что происходит, как это отлаживать и как поддерживать. Как подсчитать определитель у определённой таким образом матрицы - непонятно. Из лемма Йонеды это никак не следует.

НЛО прилетело и опубликовало эту надпись здесь

Да хоть тот же ghc, например. 

То есть в компиляторе всё того же Haskell.

Market cap у какого-нибудь cardano, где это используется — 14 миллиардов, входит в топ-10

А почему не Hamster Combat? У него тоже была большая капитализация.

Или в гитхабе для анализа исходников.

Где я могу увидеть этот анализатор? На каком языке он написан?

Или в фейсбуке антиспам. 

Я помню, как фейсбуковский антиспам не мог ничего сделать против одного отморозка, который призывал к убийствам и в каждый комментарий вставлял картинку.

Антиспам гордо рапортовал, что на картинке не обнаружено ничего плохого...

Мощная система. И что, тоже на Scheme написана?

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

Ну то есть вы не знаете, как считается определитель.

Этому обучают на профильных факультетах. Примерно на первом курсе.

обобщается до потребностей физиков с их физическими теориями (чё-то там про ОТО, струны, суперсимметрии, вот это всё — я в этих приложениях не настолько шарю, чтобы говорить что-то определённое).

Если не шарите - попробуйте восполнить оскорблениями. Расскажите им про помойных червей и обезьянок в зоопарке. Они будут вас внимательно слушать.

НЛО прилетело и опубликовало эту надпись здесь

Да, который, в свою очередь, используется в куче упомянутых ниже приложений. Чем плохо?

Тем, что gcc используется несколько шире.

А, то есть, теперь какие-то измеримые критерии вам не нужны? Ну понятно.

Заявления каких-то компаний и базворды в их отчётах - так себе аргумент. И тем более их капитализация.

По вашему нет компаний с большей капитализацией, которые используют Visual Basic?

Внутри кодовой базы гитхаба. Вероятно, для этого нужно туда устроиться.

Ну то есть вы предполагаете, что она там есть.

А я предполагаю, что там С++. Или Go. Или Rust. Или Visual Basic. Попробуйте опровергнуть.

У вас аргументы всё мощнее. А я помню, как LLM рекомендовала пользователю пиццу с клеем, или что-то такое. И что теперь это говорит об ООП, с использованием которых по-вашему сделаны LLM?

Это говорит о том, что никакой "защиты от ошибок" в Хаскелле нет. Раз один городской сумасшедший смог её обойти самым примитивным способом.

Как вы сделали этот вывод из моих слов? Или это открытая вами теорема, доказательство которой — ненужная мелочь?

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

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

НЛО прилетело и опубликовало эту надпись здесь

Если бы вы разбирались в теме, то аргументация звучала бы так:

Scheme и чисто функциональные языки активно применяются в области X. Да, они не подходят для программирования контроллеров, но пример современного использования можно найти в книге Y.

Для примера: вот код, который описывает математическую матрицу средствами Haskell. После того, как вы определили матрицу таким образом, вы можете легко производить над ней операции вот так:

Я допускаю, что вам интересно рассказывать про лемму Йонеды. Но вот что важно: вас про лемму Йонеды и капитализацию криптовалют никто не спрашивал.

Так что я не берусь вам ничего объяснять - потому что мне очевидно, что вы ничего из моих объяснений не поймёте. Вы - гений, вы знаете лемму Йонеды. Нам всем остаётся только внимать такому великому гению, как вы.

НЛО прилетело и опубликовало эту надпись здесь

Вы написали много про меня, и ничего по теме

НЛО прилетело и опубликовало эту надпись здесь

слушайте, вы настолько точно изложили МОЮ точку зрения, что Вам огромное сердечное спасибо! Прям в закладки добавлю и буду ссылку давать на этот текст, когда очередной раз увижу выступление о монадах :)

НЛО прилетело и опубликовало эту надпись здесь

ХЗ, ООП работает в каждой первой программе.

если про него что-то и есть, то как с той демократией по Черчиллю: "демократия плоха, но на сегодня все прочие варианты хуже" (цитата по памяти)

НЛО прилетело и опубликовало эту надпись здесь

я ХЗ что там в смолтолках, а пример ООП есть даже в простом банальном Си - вот этот вот указатель FILE * и всякие fopen, fclose с ним связанные.

Люди, которые придумали FILE*, fopen и fclose, такого слова-то, как ООП, не знали. Его не придумали ещё тогда.

FILE* – это адрес в памяти дескриптора файла.

Ну я, например, не вижу эту жопу повсюду :)

НЛО прилетело и опубликовало эту надпись здесь

а нет такого языка.

даже на лиспе если начать описывать те же матрицы, то снова получится ООП

НЛО прилетело и опубликовало эту надпись здесь

я вообще говорил о том, что поскольку нас окружают различные объекты, то отвергать ООП неправильно. В этом будет причина (одна из причин) непопулярности языков чисто ФП.

ведь то, что ООП на чисто ФП языках довольно сильно затруднён - факт.

Нас окружают объекты совсем не в смысле ООП.

НЛО прилетело и опубликовало эту надпись здесь

Там всё — файл объект

кстати, может быть именно поэтому смолтолк и план9 не обрели свой успех?

берём любую (ЛЮБУЮ!) вещь, хоть ООП, хоть ФП, хоть фанатство к файлам. Доводим её до абсолюта и вот вам... совершенно ненужная хрень на выходе.

Там, где ООП не нужен, он, разумеется, не нужен.

Там где нужно ФП, оно, разумеется, нужно.

ну а современные популярные языки позволяют И то И другое, а при необходимости поставить ИЛИ - можно ставить ИЛИ

НЛО прилетело и опубликовало эту надпись здесь

У меня всё это вызвало стойкое ощущение, что перед нами - эпические усилия по изобретению колеса.

Вот что делает код:

команда пуэп 64 ошибка o8 o16 o8 o8 o16 o16 o16 o8 ostr)

???

Он создаёт ошибку? Вызывает ошибку? Почему нельзя записать его как

{

"to": "пуэп",

"cmd": "error",

"list": [o8, o16, o8, o8, o16, o16, o16, o8],

"ostr": true

}

и интерпретировать????

Его можно "передать в систему и не беспокоиться о внутренней реализации?" Кажется, кто-то только что изобрёл Observer, Command и Strategy. А может даже и event-based system и хэш-таблицы.

Макросы? Кто-то изобрёл Interpreter и DSL.

Функции как переменные? Указатели на функции были ещё в C.

Лямбды и создание функций на лету, map и т.п.? Давно есть даже в C++.

Рекурсия никуда не пропадала.

Требования писать функции чисто и по возможности использовать иммутабельность - были ещё в учебниках 1980-х.

Этот код ничего не ДЕЛАЕТ. Он говорит о том, что в протоколе работы с устройством "пуэп" есть собственная команда этого устройства с кодом 64, которую мы называем "ошибка", имеющая девять выходных параметров определённых типов.

Просто декларативное описание протокола работы.

Можно написать, например,

(команда http "GET" get istr ostr)

и будет автоматически сгенерирован код простейшего веб-браузера.

Записать это, конечно, можно в любом виде, но предложенные вами в данном примере 5 типов синтаксических разделителей для выражения простой мысли выглядят чудовищно.

и будет автоматически сгенерирован код простейшего веб-браузера.

А поддержка JavaScript в этом браузере будет?

Я вот специально зашёл на https://try.scheme.org/ и вбил в строку выполнения (команда http "GET" get istr ostr)

Получил ответ:

ERROR IN console@1:2 -- Unbound variable: |\xd0;\xba;\xd0;\xbe;\xd0;\xbc;\xd0;\xb0;\xd0;\xbd;\xd0;\xb4;\xd0;\xb0;|

Какой-то плохой браузер получился. Мне не подходит.

А поддержка JavaScript в этом браузере будет?

Ну извините, бесплатно – берите что дают. Без джаваскрипта.

Я вот специально зашёл на https://try.scheme.org/и вбил в строку выполнения (команда http "GET" get istr ostr)

Так вам ещё нужен весь остальной код программы, чтобы такая команда работала.

Здесь от базового синтаксиса Scheme только строковый литерал "GET".

НЛО прилетело и опубликовало эту надпись здесь

Что значат все эти слова?

Начальное представление о значении этих слов можно получить в Википедии

НЛО прилетело и опубликовало эту надпись здесь

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

Для Haskell есть даже сервис поиска функций по сигнатуре (!) в библиотеках по всей репозитории. А библиотек там, поверьте, не мало. Для подключения к Postgres - не менее дюжины, с примесями ОРМ и без. Там и свой crates и cargo и вся инфраструктура есть давным давно (кроме отдельного IDE). Но вроде ситуация от этого не меняется.

ну, зато полезные приложения на хацкеле я встречал: один из оконных менеджеров, например, ну и архиполезнейшая хреновина - pandoc.

может быть, именно потому они и существуют, что упомянутую оснастку для этого языка сделали?

Это называется "не прочитал, но своё мнение я скажу". Так и я об этом же - инфраструктура есть, но популяризации она не способствует.

НЛО прилетело и опубликовало эту надпись здесь

Что конкретно исследуют эти инженеры при помощи scheme и где познакомиться с результатами?

НЛО прилетело и опубликовало эту надпись здесь

Удручающе напоминает "великую теория Смысл-Текст" Мельчука и Жолковского. В ABBYY на её основе лет 10 делали систему автоматического перевода - и так и не сделали.

НЛО прилетело и опубликовало эту надпись здесь

Однако на ООП реализовано множество приложений, которыми мы пользуемся каждый день. В том числе и языковых моделей.

В то время как другие были заняты изучением обезьянок в зоопарке. Возможно, как раз для этой важнейшей задачи Scheme и является крайне востребованным языком.

НЛО прилетело и опубликовало эту надпись здесь

Предлагаю вспомнить ещё один успешный проект на Racket - Perl 6.

Им тоже никто не пользуется.

НЛО прилетело и опубликовало эту надпись здесь

Тем не менее Perl 5 продолжает обновляться и у него на порядок больше пользователей.

Очевидно, он позволяет решить больше задач и более удобен.

НЛО прилетело и опубликовало эту надпись здесь

Вам стоило бы немного поизучать логику. Аргументация оскорблениями (то у вас обезьянки в зоопарке, то копошение червей у мусорного пакета) - признак небольшого ума.

НЛО прилетело и опубликовало эту надпись здесь

Обратитесь к обезьянкам в зоопарке и к помойным червям. Вы явно эксперт в этой области, они с удовольствием вас послушают. Уверен, вы просто раздавите их вашим космическим интеллектом.

НЛО прилетело и опубликовало эту надпись здесь

Скажем так - этот язык появился раньше Perl и с тех пор особо не развился. Никаких преимуществ перед JavaScript не обнаружено.

Невероятные технологии из 1985 года.

Возможно, в следующей статье нам расскажут про язык макросов в C.

А так, конечно, после волны скриптовых языков начала 90х всё это уже не актуально. В JavaScript уже в 2000 году были и деревья, и функции как значения и даже eval.

Что характерно, это пишет человек, написавший статью про программу из 200 строк для корректного сравнения объектов в JavaScript :)

Причём программа-то хорошая и нужная, но вот 200 строк на примитив equal? - нужен ли нам такой 2000 год?

Ну, за 10 лет прошедшие с написания той заметки я несколько вырос - а Scheme неизменен с 1985 года.

Последний стандарт Scheme принят в 2013 году, SRFI – в 2023. Подозреваю, что за это время универсальное средство сравнения объектов в джаваскрипте так и не появилось, потому что джаваскрипт вообще – антипаттерн проектирования ЯП.

И как новый стандарт SRFI повлиял на популярность языка? Fortran тоже в 2018 году обновился.

Сравнивать в JavaScript сложнее, чем в Scheme, потому что в JavaScript не все типы сводимы к деревьям. А так-то готовые методы есть в underscore и lodash.

Вообще, JavaScript наглядно доказывает, что языки программированяи бывают двух видов: на одни все жалуются, а другими никто не пользуется. Lisp-оподобные языки были популярны как скриптовые языки в больших системах (с тех времён уцелели Emacs, Mathematica, Gimp) в те времена, когда документации было мало и разработчику приходилось работать лексером и парсером. Но почему-то как только появились Perl, а потом Python, Ruby, JavaScript и Lua, именно их, при всех недостатках, стали понимать интерпретаторы.

За 10 лет функционального ренессанса так и не случилось. А всё, что действительно было нужно, давно перенесли в мейнстримовые языки.

  1. Фортран обновился в 2023 году и активно используется в своей области, входя в десятку наиболее используемых ЯП.

  2. Scheme не является скриптовым языком. Это компилируемый (при необходимости) язык программирования высокого уровня.

  1. Ну вот видите. Язык прошёл проверку временем. В отличии от Scheme.

  2. Судя по той же таблице популярности, Scheme - это эзотерический язык где-то между Closure и Brainfuck

Ваши представления о языках ФП тоже немного подустарели.

Clojure (кстати, тоже Лисп) не более "эзотерический" в 2024, чем, скажем, Ruby, если исключить большее количество легаси из-за старости второго. Можете ознакомиться со списком компаний использующих Clojure, от Apple до Netflix. Популярная графовая БД Datomic тоже полностью написана на Clojure.

Closure в 2024 достаточно эзотеричен, чтобы на него почти полностью отсутствовали вакансии. C 2007 года его много где могли попробовать, но в отличии от PHP и JavaScript, не нашлось ни одной области, где он бы обеспечил хоть какое-то преимущество над более простыми решениями.

nim и Nemerle тоже где-то пробовали. А на Lotus до сих пор что-то в каких-то компаниях работает.

Почти полностью отсутствуют вакансии где, в России?

C 2007 года его много где могли попробовать

А почему попробовать должны были именно там, где вы ожидали? Я же привел примеры и ссылку.

PHP незаменим из-за охренительного количества легаси. Javascript, как рантайм - из-за браузера, а как язык оказался хуже, чем десятки надстроек над ним. И ClojureScript, как бы иронично не звучало, один из них.

У меня https://clojurejobboard.com/ открылся как пустая страница.

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

Так страница написана на джаваскрипте.

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

Так и Лисп не эзотерический язык. Clojure нормальный диалект Лиспа, только поверх JVM. Могу понять людей, которым не хотелось писать на Джаве, когда они знают Лисп.

Могу понять даже людей, которые пишут на кроссплатформенном и Тьюринг-полном языке Brainfuck.

Вы говорили про отличия от лисп а есть ли в ским библиотека по типу cffi для интеграции сишного кода? Если есть то вопрос о недостатке библиотек не слишком актуален :)

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

В этом плане интересная работа проводится в Gambit Scheme (я привёл ссылку на лекцию в статье), где прямо посреди скимовского кода можно писать императивные операторы с питоновскими вызовами чего угодно. И автор прямо в видео показывает, как он pip'ом какую-то там полезную примочку подтянул и тут же из скима вызвал. Тем более, к питону концептуально проще цепляться, чем к си – он тоже динамический язык.

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

Я лично в целом сторонник микросервисной архитектуры, и считаю, что, по большому счёту, если сокеты есть (а они в скиме есть на уровне конкретных реализаций) – то уже жить можно.

поскольку дискуссия пошла несколько "не туда", предлагаю ещё одну веточку

я вот вижу неплохие перспективы LISP на поприще реализации интерпретаторов каких-то языков программирования.

Вот, скажем, нужен нам э... ну аналог Lua в э... ну пусть будет Rust.

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

Так вот, в этом месте возникают вопросы "взять готовую LISP машину и встроить к себе в проект на C/Rust/Go/брейнфак".

Можете что-то об этом сказать?

Мысль Ваша движется в правильном направлении.

Более того, на сегодня подавляющее большинство компиляторов использует в качестве промежуточного представления кода программы AST деревья, которые по сути являются специализированным диалектом Лиспа. Так что можно сказать, что программа на Rust фактически сначала транслируется в Лисп (AST дерево) фронтендом компилятора, а потом уже бекенд компилятора транслирует AST дерево в машинный код.

И одно из применений языков Lisp и Scheme – это как раз скрипты для прикладных программ. Например AutoCAD скриптуется на AutoLisp, GIMP – на TinyScheme. Это также к вопросу об обработке изображений.

Так что можно сказать, что программа на Rust фактически сначала транслируется в Лисп (AST дерево) фронтендом компилятора, а потом уже бекенд компилятора транслирует AST дерево в машинный код.

это-то я понимаю, но я хочу пользу от именно scheme заполучить. то есть я хочу вместо libast.so (который в общем виде придётся по большей части писать самому) использовать libscheme.so, который условно говоря "готов" и позволяет реализовать built-in функции моего языка не на C/Rust/Go, а прямо на scheme/lisp.

В принципе, задача решена в книге Writing an Interpreter in Go (только для Go). Там пишут JS-подобный язык (даже с макросами) и спокойно обходят эти S-выражения.

Аналогично есть уже нативные:

LUA - https://crates.io/crates/mlua

JS - https://github.com/Bromeon/js-sandbox

э... вы не совсем поняли мой вопрос.

смотрите, я пишу интепретатор нового (или старого - не важно) языка.

что мне для этого нужно?

  • распарсить всё в токены,

  • упорядочить те токены в правильном порядке (вот здесь где-то и получится набор s-выражений)

  • выполнить те s-выражения какой-то машиной

и вот если с первыми двумя задачами прекрасно справится какой-нибудь аналог yacc, то если я возьму для третьей какую-либо LISP-машину, смогу ли себе сэкономить в разработке.

типа к LISP-машине я буду приписывать библиотеки на LISP'е

типа используя LISP-машину я не пишу свою VM

в этом месте интересно использование той Scheme/LISP как э... встраиваемой функции, вызываемой из libfoobar.so. Настройка этой libfoobar на использование того или иного метода управления памятью (при встраивании хорошо бы иметь единообразную систему и там и тут) и интеграцию, скажем, с асинхрой/процессами итп.

есть хауту на эту тему?

В уже указанной книге написанию такого интерпретатора на Go посвящены главы Evalution и Evaluting the Interpreter. Сам автор указывает, что его реализация обхода аналогична интерпретатору из 5-ой части SICP.

Набор s-выражений здесь выстроен в AST (Abstract Syntax Tree). В принципе, никаких принципиальных отличий от Scheme нет - просто yacc позволяет сгенерировать лексер и парсер, а в лиспоподобных языках лексер и парсер - белковые (то есть это дерево строит сам программист).

Можно попросить интерпретатор, чтобы он дёргал предустановленные функции из C-библиотеки. Подключить их можно, например, так: https://dev.to/metal3d/understand-how-to-use-c-libraries-in-go-with-cgo-3dbn

На мой взгляд, использовать yacc вне контекста написания компилятора – очень мощное извращение. Всё-таки расписывание контекстно-зависимой грамматики – это не то, чем обычно хочется заниматься в жизни.

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

Говоря проще, LISP - это JSON с макросами.

Нет, потому что Лисп – это как данные, так и имеющий определённую семантику код, а JSON – только данные.

Если же S-выражения вас интересуют только как промежуточная форма представления данных, то вряд ли вы на этом сможете что-то выиграть от использования интерпретатора Лиспа.

я рассчитывал, что в этом случае, можно ПЕРЕиспользовать кем-то написанный на LISP'е код для реализации built-in функций нового языка.

вот, например, sort. Так или иначе он есть в любой стандартной библиотеке языка.

если мы пишем новый язык и берём свой интерпретатор s-выражений, то эту самую сортировку придётся ваять или на этом новом языке или на С/Rust (или на чём мы там пишем) или написать её прямо на уровне s-выражений.

если на уровне этих выражений LISP, то появляется шанс взять что-то готовое.

то есть я воспринимал это так.

Ну смотрите, в языке же всё завязано одно на другое.

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

Мы же программируем, наверное, не альтрнативную синтаксическую обёртку над функциями Лиспа (что довольно бессмысленно), а новый язык со своей собственной семантикой. А если брать функции Лиспа, так надо не выпендриваться, а записывать их вызовы на Лиспе.

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

если мы говорим об инженере-исследователе, то ему лучше использовать какой-то язык ВЫСОКОГО уровня (LISP я бы назвал языком низкого уровня, именно из-за отсутствия многих эксплуатационных/тулзовых вещей)

типа "если вы хотите понимать, как работает VM практически любого языка, то вот вам пример". Не более того.

PS: emacs вроде бы на лиспе написан.

поскольку это очень большой проект, то из него можно было бы выделить какие-то компоненты в libfoobar.so и использовать в других программах. Ту же работу с клавиатурой, с терминалом, с Xorg, итп.

Не знаете, что-то такое есть в природе?

Лисп язык очень высокого уровня, и именно поэтому в нём нет эксплуатационных/тулзовых вещей. Он выше их уровнем.

Сам я использую Scheme для реализации некоторого метаязыка – надстройки над сервисами, написанными на других языках. А всякие базы данных, GUI интернет и прочее – они ниже уровнем, в условном “ассемблере”. Фактически я имею возможность давать описание задачи компьютеру на языке, приближенном к естественному, а программа на Scheme сама преобразует их семантику к операциям, исполняемым при помощи других прикладных программ, и сама генерирует для этого код.

А VM ко всему этому вообще не имеет никакого отношения. Лисп – компилируемый (при необходимости) в машинный код язык.

Он выше их уровнем.

это субъективизм вида схожего с "человек королевских кровей выше прочих уровнем".

почему? потому что королевских кровей.

Это объективная картина, потому что семантика Лиспа, построенная на базе аппарата лямбда-исчисления, позволяет повышать уровень абстракции неограниченно. В то время как в мейнстримных языках программирования мы всегда ограничены их базовыми конструкциями.

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

Можно сказать по-другому. Лисп позволяет непосредственно описывать денотационную семантику, а не только операционную, то есть его формы могут соответствовать онтологии предметной области, а не просто поведению программы.

позволяет повышать уровень абстракции неограниченно

семантика ЛЮБОГО языка позволяет это делать.

взять например ASM. вы можете манипулировать словами и байтами, а можете оперировать объектами, содержащими объекты, содержащими объекты.

Конечно, можно сказать, что и объект может иметь сколь угодно сложное поведение, но всё равно мы остаёмся зажаты в тисках интерфейса между объектами.

ну а у LISP разве не так?

Так я как раз не хочу ничем оперировать. Или хочу оперировать как можно меньше.

ASM не позволяет делать утверждения, а Лисп позволяет. ASM просто задаёт команды.

Это, кстати, значительная проблема при обучении ФП людей, ранее знакомых с императивными языками – отучить их мыслить поведением.

Так я как раз не хочу ничем оперировать. Или хочу оперировать как можно меньше.

так ведь это желание невозможно исполнить, если вы программируете что-то более-менее отлчиающееся сложностью от чисел Фибоначчи.

сложили числа в матрицу - появилось понятие матрицы и операторы, ей манипулирующие. и вот мы пришли к объектно-ориентированному программированию не уходя далеко от математики

при том, что в современном мире чаще всего понятия "математика" и "программирование" вообще не имеют точек пересечения.

ASM не позволяет делать утверждения, а Лисп позволяет.

чем макросы или функции - не утверждения?

Тут надо внимательно следить за руками. Хотя математика исторически и появилась как способ подсчёта отнимаемого у крестьян зерна, но в современном понимании не является манипуляцией с числами. И операторы над матрицей или функции в математике просто фиксируют отношения между правой и левой частями. Например, в математическом утверждении sin(x) = cos(x+pi/2) нет никакого вычисления или манипуляции, это просто денотация свойства синуса и косинуса.

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

Если бы мы не умели вычислять значения синуса и косинуса, то фиг бы мы вообще что получили императивным способом определения функции из равенства sin(x) = cos(x+pi/2). Хотя как база для символьных преобразований – оно вполне рабочее.

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

про математику очень много в книге, что рекомендуется в статье

там чуть ли не все программы что в примерах - вычисление каких-то математических значений.

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

Извините, если, математику Вы в виду не имели.

Ну в книге в первых главах чисто учебные примеры. На математических вычислениях некоторые вещи проще объяснять, так как модель предметной области всем понятна.

Это кстати проблема многих книг и собеседований: там примеры, которые среднему программисту НИКОГДА не встретятся.

Средний программист НИКОГДА не программирует ряды Фибоначчи, факториалы, биномы Ньютона. Никогда не опускается до разбора "что там за алгоритм сортировки под капотом stdlib" и так далее

Ну в таком случае эта книга для программистов выше среднего. Собственно, это действительно так, так как это учебное пособие для курса системного программирования в одном из ведущих мировых вузов.

Важное уточнение - учебное пособие приблизительно 40 летней давности. С тех пор индустрия шагнула немного вперёд. И сам курс давно читают с примерами на Python 3.

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

Новый курс вообще совсем поверхностный, а не то что просто переведён на Python.

А работают на умных должностях китайцы и прочие приезжие.

Ну я бы сказал, что всё намного проще - с появлением более лаконичных и читаемых языков Scheme отправился вслед за Smalltalk и Simula67

Если вы видели старый и новый курсы MIT, то проблема там не в языке.

Эта книга - 1985 года. Тогда ещё даже Mathematica не было.

По сути же - системы доказательств и преобразований из формулы в формулу не особенно популярны за пределами узкого круга тех, кто разрабатывает Coq. Ещё Пуанкаре говорил, что великие математики открывают теоремы - а посредственные математики нужны, чтобы их доказывать.

Если вычислительная математика - то компьютер просто используется как очень мощный калькулятор, там LISP-ов нет, а используется C-подобная CUDA или даже Fortran (на суперкомпьютерах до сих пор). А логическая математика - это крайне узкая область и описание её объектов очень утомительно: приходится разворачивать каждое "после тривиальных преобразований получим". Гротендик и вовсе считал такие инструменты концом математики как науки.

Я занимаюсь системами управления, например.

а в системах управления разве объекты не встречаются?

Зависит от использованной модели.

ну вот допустим есть выключатель.

нажали на него (контакт замкнулся) - лампочка загорелась

повторно нажали на него (контакт снова замкнулся) - лампочка погасла

плюс есть дребезг контактов (200 мс при нажатии/отжатии)

и допустим мы программируем "умный дом" - то есть таких выключателей, подключенных к одной программе, может быть множество.

Можете набросать рыбу программы кнопка-лампочка на функциональном языке (и чтоб понятие "объект" было не нужно)?

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

А когда вы введёте обратную связь, то вам не нужно будет хранить в программе состояние объекта.

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

без обратной связи в системе достаточно иметь таймер отсчёта времени

Так, как вы сформулировали задачу, вы никогда не знаете, горит лампочка или нет. Во-первых, вы не знаете начального состояния лампочки до запуска вашей программы. Во-вторых, у вас нет гарантии, что выключатель работает правильно (да и про ровно 200 мс на каких скрижалях написано?). В-третьих, у вас нет гарантии, что электрик Дядя Вася в какой-то момент не замкнул выключатель отвёрткой.

Поэтому у вас будет поле в объекте "состояние лампочки", с одной стороны, и фактическое состояние лампочки, с другой стороны. И они могут разойтись между собой.

Всё на самом деле ещё сложнее. Реальная история из жизни. В одном приборе было установлено механическое реле, состояние которого контролировалось программой через замыкание контрольного контакта, а всего в контактной группе замыкалось много контактов. И вот получилось так, что в процессе транспортировки реле сотряслось, и разные контакты в контактной группе оказались в разном положении. Контрольный контакт оказался замкнут, а исполнительный отошёл от замкнутого положения (или наоборот). И неудачно написанная программа заблокировалась, так как она считала реле замкнутым и не видела оснований подавать ещё одну команду на его замыкание. Так что даже с обратной связью всё не так просто, и никаких программных состояний и прочих неконтролируемых теоретических допущений о состоянии управляемых объектов быть не должно. А в этом устройстве с тех пор горячие клавиши для команд управления отрабатываются программой даже тогда, когда команды исчезают из меню на экране. Пользователю виднее. Ну, программисты зато прокатились в командировку 4 часа на самолёте.

Если вам интересно, то вот почти реальный код на Scheme из системы управления объектом, касающийся подсистемы управления электропитанием:

(служба 111 сервер1 пуэп)
(команда пуэп 61 вкл-выкл i16 i8)
(команда пуэп 62 описание i16 o8 o16 o8 o8 o8 ostr)
(команда пуэп 63 статус i8 o8 o8 o16 o16 o8 o8)
(команда пуэп 64 ошибка o8 o16 o8 o8 o16 o16 o16 o8 ostr)
(команда пуэп 65 включить i16 таймаут 20)
(команда пуэп 66 выключить i16 таймаут 20)
(команда пуэп 67 блокировать i16)
(команда пуэп 68 разблокировать i16)
(команда пуэп 69 состояния o8 o8 o16 o8 o8 o8 o8 o16 o8 o8)
(команда пуэп 70 вкл-выкл-дизель i8)
(команда пуэп 71 вкл-дизель)
(команда пуэп 72 выкл-дизель)

Это макросы, которые генерируют фактический исполняемый код для команд управления.

Они находятся ближе к нижнему уровню абстракции в программе. На самом верхнем уровне находятся команды вроде (условно):

(время 9:00) (заварить кофе)

а система уже сама разбирается, что и как для этого нужно сделать.

Если бы я использовал тут объектную модель, то я бы столкнулся, как минимум, со следующими проблемами.

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

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

  3. Для малейшего редактирования логики был бы нужен программист, причём перманентно озабоченный проблемой из пункта 2. Либо пришлось бы писать какой-то навороченный редактор сценариев для пользователей. Это возможный ход, и его проходили в отрасли много раз, начиная с JCL, но результаты каждый раз ужасны, так как неизменно не хватает функциональности для сложных случаев.

понятие "сварить кофе" в любом случае предполагает управление кофейником.

а программирование последнего фиксирует перечень возможных операций (привязывает апи к процессу) и перечень возможных кофе машин (привязывает апи к объекту)

и вот не мытьём так катаньем у нас всё равно есть ООП

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

Поэтому в принципе, конечно, натянуть ООП на это можно (и это неоднократно делалось), но некоторые проблемы я указал в соседнем посте. Тут просто происходит некоторая подмена понятий, когда вместо семантики “сварить кофе” рассматривается семантика “включить кофе-машину”. Методом же символического продукционного вывода мы можем преобразовывать семантику совершенно корректно.

в заказе тоже будут фигурировать объекты вроде магазина и банковской карточки

особенно высокоуровневые алгоритмы предполагают именно манипуляции объектами, а не числами

кстати, манипуляции строками и числами - это уже объектное программирование, просто виды объектов в данном случае предопределены

Вы вправе всё, что угодно, называть объектами, но реквизиты магазина и банковской карты - это структурированный текст. В Лиспе он будет, несомненно, синтаксически представлен S-выражением, которое по своей семантике, скорее всего, будет иметь тип список.

реквизиты магазина - структурированный текст

а реквизиты двух магазинов? или двух банковских карточек - это уже два структурированных текста, описывающих раздельные экземпляры ОБЪЕКТОВ

и потом, в словосочетании структурированный текст, слово структурированный имеет корнем - структура.

а структура чего? того самого объекта

Это список, состоящий из двух списков, не равных между собой.

Не надо усложнять. А то я вас спрошу, какой смысл в двух экземплярах объекта, содержащих данные одной банковской карты.

вот у вас сущности

  • список состоящий из двух списков

  • список состоящий из двух чисел

  • список состоящий из числа и строки

  • список состоящий из двух строк

  • просто число

  • просто строка

это всё объекты и есть, как от них не отворачивайся

В смоллтоке разве что. И то я не уверен относительно экземпляров чисел.

да даже в ассемблере

НЛО прилетело и опубликовало эту надпись здесь

в приведённом примере не scheme (это так, сноска)

Матрица размера n×m над полем F — это просто параметризованный F и индексированный n m тип Mat F n m, для семейства которых определены операции и константы

тип для которого определены операции, объект, и так далее

всё это во многих языках синонимы.

НЛО прилетело и опубликовало эту надпись здесь

Ага, если пользователь может описывать новые типы и инстанцировать отдельные их значения и делает это, то он работает в ООП

Если при этом ему трудно, приходится преодолевать или изобретать велосипед, то это говорит лишь о том, что язык с ООП дружит слабо (не о том, что на языке нельзя ООП писать).

НЛО прилетело и опубликовало эту надпись здесь

emacs на C написан. LISP там - аналогично Python в Sublime или JavaScript в Atom, язык скриптов и дополнений.

Вроде на C написан интерпретатор Emacs Lisp, а на этом Лиспе - сам Emacs.

не знал (правда).

мне всегда казалось что это именно с ног до головы LISP приложение

Если б его писали сейчас, был бы целиком на лиспе, к гадалке не ходи. Но в те времена Лисп очень тормозил.

ZED (из недавно вышедших) написан на Rust.

Что в нём нового по сравнению с Sublime - не очень ясно.

За Scheme можно было ещё словечко замолвить. Racket есть в Termux пакетом, а вот пакета Julia в Termux нет. И на Андроид есть диалект Lisp как относительно рабочее приложение, а на iPad есть прямо таки Scheme, хотя и называется LispPad. И Scheme развивается достаточно медленно и поэтому везде более-менее одинаковый, чем выгодно отличается от того же Python который почти везде не актуальный.

Книжка SICP в 2022-м году вышла перепетая на JavaScript.

Для айфона есть Gambit REPL.

Эпический тред там выше про ООП, ФП, типы, кто из них круче и всякое такое. Обычно не участвую в таких дискуссиях, но тут не удержаться. Печально, что люди так критически относятся к новой для них информации.

Вот промисы в том же JS: есть две ветки выполнения - resolve и reject - и состояние, упакованное в контейнер. Пусть @illinav поправит, но очень похоже на монаду.

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

@RikkiMongoose.Кстати, вот насчёт типизации и гарантий в "compile time" (в широком смысле), никто же не будет спорить что "use strict" штука полезная.
ESLint, TypeScript - тоже классные инструменты. Насколько понимаю, Haskell и, тем более, Idris, например, - это как TypeScript на максималках.

@ednersky Спор выше по сути не про ООП, а про слабые и сильные системы типов. И вот как то так получилось, что у большинства ООП-языков система типов слабая (по сравнению с). И приходится выкручиваться паттернами и линтерами и тестами там, где могли бы эффективнее работать типы.

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

Что популярно и где используется - вообще странный аргумент, вот Blackbird - чудо своего времени, но использовался крайне ограниченно, так и тут.
Возможно, что то из функциональных (в том числе "экзотических") языков ещё перейдёт в тот же JS / TS (и другие мейнстримные языки). Такое уже не раз было...

Вообще система типов и ФП - это довольно независимые вещи. Хотя своего наивысшего развития, безусловно, система типов достигает в типизированных ФП языках. Но Лисп и его диалекты основаны на бестиповом лямбда-исчислении, и это имеет свои практические преимущества, особенно в системном программировании, так как архитектура фон Неймана бестипова.

Что касается промисов (которые вроде как раз из Scheme изначально и пошли), то они, скорее, представляют собой организацию ленивого вычисления руками. Но пользы от этого, честно сказать, гораздо меньше, чем от настоящего ленивого порядка вычислений, как в Хаскеле. Хотя иногда бывает полезно.

А с сильной системой типов - всё это ещё и безопаснее и легче читается (просто по аннотациям).

Я так вижу (ц), что сильная система типов - это упрощение нагрузки на разработку редактора/IDE и перенос этой нагрузки на разработчика.

И ТОЛЬКО. (других применений сильной типизации НЕТ)

адепты сильной типизации чаще всего аппелируют к примерам, вроде вот этого мема:

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

Например ситуация подобная мему в таких языках, как Perl невозможна в принципе (а там с типами ситуация ещё более вольная чем в JS).

Вообще, этот мем Ларри Уолл разобрал в своей книжке ещё ЕМНИП в каком-то лохматом 199x году - задооолго до собственно появления понятия "мемы".

Поднимаемый хаскелистами вопрос с ФП вообще не в сильной или слабой типизации, а в системе типов и их выводимости. Скажем, в Scheme сильная типизация, но вот только в ней всего пять типов (или чуть больше, в зависимости от реализации).

А что касается мема, то, конечно, это пример просто необдуманной перегрузки плюса.

а можете объяснить "на пальцах": зачем нужна эта самая выводимость типов, что она даёт? (кроме облегчения работы IDE/компилятора и никому не нужных чисел Фибоначчи)

Она даёт автоматизацию части вещей, для которых иначе надо сначала содержательно думать головой, а потом писать руками код. То есть увеличивает производительность труда программиста и надёжность программы, если предметная область вообще поддаётся содержательной типизации (категорированию). Это как с объектами: можно, конечно, декларировать, что объекты – это вообще всё, но практическую пользу от этого можно получить только в некоторых случаях.

А так пусть лучше вам хаскелисты объясняют. Я лично за бестиповое ФП.

в моей голове идеально примерно так:

  1. язык должен уметь работать с объектами (= типами, в моей голове это одно и то же), но не должен их навязывать

  2. язык должен уметь и в ФП (П-подход) и в обычный императивный. Смешивание - наше всё. Даже к SQL рано или поздно приделали PLSQL. Почему? Потому что банальная переменная внутри цикла и чистая императивщина зачастую сокращает число кода в разы

  3. из проблем (вроде двусмысленности операторов) нужно делать выводы приводящие к устранению именно этих проблем, а не как с мемом выше.

Самым близким к идеалу, по моему мнению был Perl.

в нём парсеры можно было писать собирая каскады map{lambda}-map-map-map, а можно на регекспах, а можно на классической стейтмашине с goto.

Принцип тимтоуди в сочетании с KISS - наилучшее приближение к идеалу.

Не являюсь экспертом по перлу, но в моём понимании он – классический императивный язык, весьма запутанный к тому же. Наличие лямбды не особо приближает его к функциональному программированию, он императивен по семантике своих основных конструкций (как и питон). Хотя саму по себе идею заимствования lambda и map в императивных языках следует приветствовать.

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

то есть например сделано всё, чтобы если хочешь писать на ФП, то мог бы обходиться минимумом усилий и символов в строке!

там например возможно такое объявление функций, чтобы паттерн map-reduce при их использовании дальше ложился в минимум символов (чтоб лямбды даже объявлять без ключевых слов, ограничиваясь фигурными скобками).

весьма запутанный к тому же

запутанность Perl - это тоже мем.

у Perl был принцип тимтоуди. Этот принцип декларировался как помощь к KISS или лаконичности кода.

То есть открываешь любую книгу по Perl и она начинается вводными: "ребята, более простой или лаконичный код всегда лучше более сложного, запутанного!"

При этом, тимтоуди, конечно, обоюдоостый инструмент.

если у тебя только форм того же if несколько, то конечно их все нужно разобрать/понимать.

Некоторые языки в своём базисе ставили отрицание принципа тимтоуди.

Википедия о Python: В отличие от девиза Perl «есть несколько способов сделать это», Python придерживается философии «должен существовать один — и, желательно, только один — очевидный способ сделать это»[54]

когда они это декрарировали им казалось что они таким образом получат менее запутанный код. Однако потом они же в своём же setuptools запедалили классы (sic!), предназначенные исключительно для передачи настроечных аргументов к одной (одной!) функции.

Отрицая тимтоуди ушли и от KISS и от лаконичности.

А ещё в Perl был принцип построения: "частоупотребимые вещи/паттерны должны делаться просто, а сложные быть возможны".

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории