Введение
Язык Scheme (произносится "ским"), которому в следующем году исполняется 50 лет, является языком программирования, занимающим необычное место среди прочих. Это язык, который гораздо больше изучают, чем потом на нём пишут. Скорее это язык для развития ума программиста, чем для написания коммерческого кода, хотя и примеры использования Scheme в коммерческой разработке тоже встречаются. На мой личный взгляд, Scheme идеален в качестве первого языка программирования в старшем школьном и институтском возрасте, а также идеально продолжает изучение Scratch в младших классах школы и Logo в средних классах.
Достоинства Scheme:
– предельно простой синтаксис, позволяющий не отвлекаться на изучение бессмысленных синтаксических деталей;
– небольшая по описанию, но очень мощная по выразительным средствам и глубочайше формализованная семантика;
– прекрасный учебник Массачусетского технологического института по конструированию программ "Структура и интерпретация компьютерных программ" SICP, переведённый на русский язык, использующий язык Scheme;
– интерактивная среда разработки и динамическая структура языка, позволяющие не забивать голову программиста лишними проблемами и наглядно видеть результаты каждого шага программирования;
– возможность очень легко писать программы, расширяющие свой собственный исходный текст, что является одним из методов символического искусственного интеллекта.
Недостатки Scheme:
– язык редко используется в коммерческой разработке и имеет мало прикладных библиотек и фреймворков;
– к синтаксису языка с большим количеством скобочек нужно привыкнуть;
– программы в обычном стиле Scheme имеют огромную плотность смыслового содержания по отношению к длине их текста, в связи с чем их чтение человеком затруднено (а оплата за строки кода невыгодна);
– относительно небольшое сообщество.
В общем, если вы хотите привести в порядок своё понимание основных концепций программирования (или просто блеснуть академическими познаниями), учите Scheme. Если ваша работа связана с решением алгоритмически сложных задач, то вы, возможно, даже найдёте этому языку практическое применение.
Что такое Scheme?
Scheme – это диалект языка Lisp, имеющий некоторые глубокие, но не очень многочисленные отличия и потому выделенный в отдельный язык. Если вы понимаете Lisp, то без труда поймёте и Scheme, и наоборот.
Стандарт языка Scheme регламентируется документами, носящими в лучших традициях префиксной функциональной записи названия Revised Revised ... Revised Report on the Algorithmic Language Scheme, или просто R*RS. На сегодняшний день основные реализации поддерживают стандарты от R5RS до R7RS. Документ R7RS имеет объём 88 страниц, в которых полностью описаны синтаксис и семантика языка, начиная от формального математического определения семантики в лямбда-исчислении.
Также важной частью фактически используемого языка Scheme являются Scheme Requests for Implementation, или SRFI, представляющие собой предлагаемые сообществом дополнения к стандарту. Все SRFI пронумерованы, в настоящий момент их предложено ровно 255 штук. Реализации Scheme включают тот или иной набор SRFI “из коробки”, интегрированными во входной язык. Но это не так важно, так как особенностью Scheme является расширяемость входного языка его же средствами, поэтому большинство SRFI представлены макрокомандами, которые можно использовать в своих программах независимо от их наличия в дистрибутиве транслятора.
Реализаций языка Scheme очень много, многие из них входят в стандартные репозитории Linux. Заслуживают упоминания реализации MIT Scheme (она используется в SICP) и Racket (удобная графическая пользовательская среда). Сам автор пользуется реализацией Gambit Scheme, так как её интерпретатор и компилятор имеют легко собираемый исходный код без внешних зависимостей, а также в полной мере поддерживают национальные языки в идентификаторах (в Linux для этого может потребоваться пересборка). Последнее важно для создания на базе Scheme пользовательских предметно-ориентированных языков. Gambit Scheme (пока в экспериментальном режиме) поддерживает подключение и вызов библиотек для языка Python.
Наконец, необходимо отметить, что написание программ на Scheme (и других диалектах Лиспа) рано или поздно приведёт вас к редактору emacs.
Далее приведём несколько элементарных примеров кода на Scheme, ни в коем случае не имея в виду соревноваться с SICP.
Напишем программу Hello world
"Hello world!"
"Hello world!"
Вычислим 1/3 + 1/7
(+ 1/3 1/7)
10/21
Здесь мы видим, что основным элементом синтаксиса языка являются выражения в скобках (S-выражения), которые, если их интерпретировать как данные, представляют собой списки, а если их интерпретировать как код, представляют собой формы функциональных вызовов с функцией на первой позиции и её аргументами на остальных позициях. Фундаментальным отличительным свойством Scheme (и других диалектов Лиспа) является гомоиконичность, то есть одинаковое представление кода и данных. Отметим, что этим свойством обладает также машинный код, а в других языках программирования оно утрачено.
Вычислим 100!
(letrec
((fact (lambda (n f)
(if (zero? n)
f
(fact (- n 1) (* f n))))))
(fact 100 1))
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
Фактически единственным способом организации повторяющихся вычислений в Scheme, как и в лямбда-исчислении, является рекурсия. Стандарт Scheme гарантирует оптимизацию хвостовой рекурсии. Имеется в языке и свой цикл do, но он является макросом, реализуемым через хвостовую рекурсию.
Отсортируем строки в текстовом файле
(list-sort
string<=?
(call-with-input-file
"myfile.txt"
(lambda (p) (read-all p read-line))))
Обратите внимание, что нам пока что не пришлось определить ни одной функции, чтобы потом её вызывать. Со всеми этими простыми задачами мы справлялись одним вычислимым выражением.
Напишем функцию, которая из списка чего попало делает строку
(define (anylist->string args)
(string-concatenate
(map (lambda (x)
(if (string? x)
x
(object->string x)))
args)
" "))
(anylist->string '(1 2 "Hello" 3. #t))
"1 2 Hello 3. #t"
Вызовем ту же самую функцию в отдельной нитке
(thread
(lambda ()
(display
(anylist->string '(1 2 "Hello" 3. #t)))))
(мы вынуждены применить здесь функцию display, потому что результат выполнения из другой нитки сам по себе не напечатается).
Напечатаем значение, которое получило имя нашей функции
anylist->string
#<procedure #2 anylist->string>
(видно, что это какой-то код).
Напечатаем покрасивее
(pp anylist->string)
(lambda (args)
(string-concatenate (map (lambda (x) (if (string? x) x (object->string x))) args) " "))
(а здесь уже видно конкретное функциональное значение).
Создадим список, представляющий собой исходный текст программы, вычисляющей значение 2+2, и выполним эту программу
(eval (list '+ 2 2))
4
(в целом, если в вашей программе осмысленно используются вызовы eval (интерпретация данных как кода), то скорее всего за Scheme или Lisp вы взялись не зря).
Реализуем в языке оператор (если ... то ... иначе ...) и значения "истина" и "ложь":
(define-syntax если
(syntax-rules (то иначе)
((если p то x иначе y) (if p (begin x) (begin y)))
((если p то x) (when p x))))
(define истина #t)
(define ложь #f)
(если истина то "Привет")
"Привет"
Если вас заинтересует язык Scheme, то надо просто брать SICP и читать. На 6-й странице вы научитесь вычислять арифметические выражения, на 129-й – программировать символьное дифференцирование, на 329-й – писать интерпретатор, а на 524-й – писать компилятор.
Комментарии (152)
ednersky
06.11.2024 14:00спасибо за ссылку на русскоязычную книжку
PS: а каждый язык силён прежде всего инфраструктурой включения наработок на нём в CI/CD.
То есть первое, куда стоит смотреть, это "как на этом языке писать интеграционные и юниттесты", ну и как со всем этим вылезать в прод.
А как на схеме/лисп принято код тестировать?
vadimr Автор
06.11.2024 14:00С точки зрения CI/CD интерпретируемый язык вроде Lisp или Scheme очень удобен, потому что можно менять код программы прямо по ходу её выполнения, не перезапуская её. А функциональный стиль подразумевает, что каждая отдельная функция – сама себе юнит, который можно тестировать, причём в нормальном случае она не имеет побочных эффектов. Поэтому сама постановка вопроса об отдельных юнит-тестах скорее является артефактом императивных языков.
Фактически у вас среда выполнения в Scheme является просто набором функций, среди которых могут быть и тестирующие функции.
Но другое дело, что динамически генерируемый код, ради которого обычно и затевается весь этот праздник жизни, очень сложно верифицировать. Это общая проблема ИИ.
ednersky
06.11.2024 14:00я так и не понял: так таки да или так таки нет?
vadimr Автор
06.11.2024 14:00Что да или нет?
Если Scheme использовать для тех же задач, что и обычные языки программирования, то тестировать легко. Механизм функций высшего порядка является в том числе и достаточным инструментом для тестов.
Если программировать на Scheme символьный ИИ, что на каком-нибудь C++ вообще малореально, то тестирование затруднено, потому что сама фишка любого ИИ в том, что его невозможно покрыть тестами.
Обычно на Scheme хорошо программировать такие приложения, которые вообще не имеют никакой определённой прикладной логики в момент запуска, а являются некой конфигурируемой пользователем средой.
Autochthon
06.11.2024 14:00Схеме так же как и хаскел редко встречается в проде т.к требует повышенной умственной отдачи от программиста. Так сказать требует героев, а мать природа рождает дураков. Поэтому прод в основном императивка с уютными методиками поиска
ключейрешений под фонарем. Средний интеллект программиста - ограничивающий фактор на пути к "идеальным" языкам.smt_one
06.11.2024 14:00Не думаю, что дело в интеллекте. Скорее, в привычности и насмотреннности, плюс в поддержке более мейнстримных языков их сообществами и компаниями.
ednersky
06.11.2024 14:00многие языки делает не столько сам язык, сколько образованная вокруг него инфраструктура.
Вот, например я беру в руки Rust ну или JS. Задаю вопрос:
как мне создать проект? сразу получаю документ о cargo или npm
как мне тестировать проект? получаю следующий документ
где мне искать написанные кем-то библиотеки? получаю третий документ
и так далее и тому подобное.
Rust силён не столько системой управления памятью, сколько https://crates.io/.
Как-то так.
Герои требуются там, где всей этой инфраструктуры нет.
vadimr Автор
06.11.2024 14:00Вы сейчас говорите о технологической оснастке для рабочего. А языки ФП - это больше инструменты для инженера-исследователя.
Когда задача доходит до такого уровня понятности, что её можно решить типовым проектом на расте, её совершенно незачем программировать на Scheme. Разве что в учебных целях.
ednersky
06.11.2024 14:00я сейчас говорю о причинах столь малой популярности языков ФП.
задача: "я хочу взять готовую библиотеку работы с БД MySQL и применить её в своей программе".
как я решаю её на Rust? Я пишу в командной строке
$ cargo search mysql
Как я буду решать её на Lisp/Scheme?
я пойду гуглить в интернет. и что важно, скорее всего не найду искомого (для mysql может что и найдётся, но для 9/10 поисков - нет)
А языки ФП - это больше инструменты для инженера-исследователя.
не очень понимаю, почему ФП подходит исследователю лучше, чем не ФП.
Исследователь он что делает? Ну например пытается "зрением" некоего робота оснастить. В этом месте помимо самого "зрения" он решает кучу (КУЧУ!) попутных задач и задача вроде "положить результаты измерения в БД" становится "проходной", "попутной" итп
Когда задача доходит до такого уровня понятности, что её можно решить типовым проектом на расте, её совершенно незачем программировать на Scheme.
То есть инженер-исследователь, потратив полгода-год на написание кода на LISP, получив положительный результат, начинает переписывать всё на Rust? А зачем ему LISP на стартовом этапе?
vadimr Автор
06.11.2024 14:00Необязательно разные задачи программировать на одном языке. И даже вредно.
Если говорить про зрение робота, то вкорячивать в его код интерфейс к конкретной СУБД – в любом случае плохое решение.
ednersky
06.11.2024 14:00интерфейс к конкретной СУБД – в любом случае плохое решение.
то есть задачи стейтфул обработки данных для LISP не подходят?
только стейтлесс?
vadimr Автор
06.11.2024 14:00Во-первых, нет никаких стейтфул или стейтлесс задач. Есть конкретные алгоритмы.
Во-вторых, желательно выбирать соответствующий задаче уровень абстракции. Где-то там внизу данные может хранить та или иная СУБД, но для алгоритма машинного зрения это точно неважно.
ednersky
06.11.2024 14:00Во-первых, нет никаких стейтфул или стейтлесс задач. Есть конкретные алгоритмы.
конкретные алгоритмы описываются некоей функцией. Если два вызова функции с одними и теми же параметрами приводят к одному и тому же результату, то это просто.
Но увы, в современном мире это далеко не всегда так. Функция при одних вызовах может сохранять/накапливать какой-то набор данных, который будет использоваться при последующих вызовах.
Чуть ли не все самообучающиеся алгоритмы на этом построены.
А потому задача "сохранить/загрузить данные в/из (БД/сети/диске/где-то)" - ну, чуть ли не рядовая.
vadimr Автор
06.11.2024 14:00Вопрос сохранения данных вообще, конечно, рядовой. Scheme в этом отношении, между прочим – удобный язык, так как не имеет проблем с сериализацией объектов. Но сохранение вообще не означает, что нужно тащить в высокоуровневый код API СУБД.
ednersky
06.11.2024 14:00Но сохранение вообще не означает, что нужно тащить в высокоуровневый код API СУБД.
что такое СУБД?
это такая хрень, которая
готова (сделана не нами)
умеет масштабироваться
предназначена для разнообразнейших поисков по сохранённым данным
храня данные БД (против хранения в переменных языка) мы получаем условно-бесплатный способ интроспекции состояния, а ещё способ воздействия на это состояние
соответственно коннектор к API СУБД может понадобиться в любом более-менее сложном приложении.
vadimr Автор
06.11.2024 14:00Коннектор – не означает само API СУБД.
В большинстве случаев, когда в реальной жизни используются простые СУБД вроде mysql, аналогичных результатов можно достичь в Scheme более простым путём – через ассоциативные списки и функции высшего порядка. Ещё и быстрее будет из-за отсутствия потерь на коннект. Конечно, это не относится к высоконагруженным и огромным по размеру базам данных, но там вообще совершенно своя специфика работы.
RikkiMongoose
06.11.2024 14:00Собственно, именно в этом главная проблема чисто функциональных языков программирования.
Они запрещают состояния. Но компьютер (и любая другая машина Тьюринга) и есть машина состояний. Пишем мы на жёсткий диск, выводим на экран, получаем запрос по сети, посылаем ответ - всё это состояния.
vadimr Автор
06.11.2024 14:00Scheme не является чисто функциональным языком в том смысле, что вполне поддерживает процедурный стиль.
Вы правы в том, что ввод-вывод компьютера технически основан на состояниях, и это не вполне гладко стыкуется с функциональной парадигмой. Но машину Тьюринга в связи с этим я бы поминать не стал, так как машина Тьюринга – это всего лишь одна из возможных абстракций для вычислительного процесса. К функциональной парадигме ближе лямбда-исчисление, которое равномощно машине Тьюринга.
Однако, на то же самое можно взглянуть с другой стороны: когда мы занимаемся какими-то формальными преобразованиями кода, например, оптимизацией, распараллеливанием, доказательством правильности – то состояния нам мешают.
illinav
06.11.2024 14:00Они запрещают состояния.
Нет, конечно. Что такое, по-вашему, монада
State
, илиST
, или явная мутабельность с линейными типами вне всяких монад?
illinav
06.11.2024 14:00Если слова
State
илиST
или «линейные типы» для вас значат то же самое, что и «закозельская кукарямба», то, вероятно, вам не стоит так безапелляционно заявлять, что функциональные языки запрещают, что — разрешают, и какие у них проблемы.
RikkiMongoose
06.11.2024 14:00К сожалению, мне нет дела до того, какие слова или выражения вы выучили. Будь то "монада", "эндофунктор", "аорист" или "закозельская кукарямба".
Если бы это было важно - это бы нашло применение где-то за пределами случайных проектов в случайных компаниях и академических исследований о заведении лямбды за сигму.
Пока же это просто до зубной боли нудная реклама, обстрел читателя кучей терминов из крайне узких разделов математики и на каждом шагу при попытке узнать подробности наталкиваешься на то, что привычные термины просто переопределены по своему.
Это применяется для написания компиляторов? Каких компиляторов? Как выясняется, это компиляторы из одного диалекта LISP в другой диалект LISP, описанные в мощнейшем университетском курсе 40-летней давности.
Это позволяет писать программы без ошибок? Как выясняется, под программой понимается не приложение, а кусок кода, который ничего не делает или считает ряд Фибонночи.
Это позволяет писать код яснее и короче? Приведённые примеры - что-то инопланетное, из них вообще невозможно понять, что происходит, как это отлаживать и как поддерживать. Как подсчитать определитель у определённой таким образом матрицы - непонятно. Из лемма Йонеды это никак не следует.
illinav
06.11.2024 14:00> пишет, что ФП запрещает состояние
> получает в ответ отсылку к стандартным и давно известным методам управления состоянием в ФП
> отвечает по смыслу «я в этом не шарю и мне это ни о чём не говорит»
> получает замечание, что если человек в какой-то теме не шарит, то не надо выступать про неё с экспертным видом
> разражается комментарием, где соломенных чучел больше, чем запятых
Топ кек.
После того, как я подытожил ваш замечательный метод ведения диалога, когда вы начинаете с «ФП запрещает состояние», а в ответ на контраргументы пишете «да это всё нинужно! тырпрайз! факториалы! фибаначи!», можно ответить на особо интересное:
Это применяется для написания компиляторов?
Да хоть тот же ghc, например. Или интерпретаторы/VM для блокчейнов (где используется что-нибудь типа CEK-машины, описанной в упомянутой рядом тоже нинужной книге). Market cap у какого-нибудь cardano, где это используется — 14 миллиардов, входит в топ-10. Кстати, и формальные методы из соседнего треда для верификации смарт-контрактов там используются. Или в фейсбуке антиспам. Или в блумберге DSL для их финансистов. Или в не-банке Mercury. Или в гитхабе для анализа исходников. Или в Standard Chartered тоже для их трейдеров-финансистов. Или в Bridgewater для похожих целей. Или в куче других мест.
Если бы это было важно - это бы нашло применение где-то за пределами случайных проектов в случайных компаниях и академических исследований о заведении лямбды за сигму.
Любой пример, который вы приведёте — случайные проекты в случайных компаниях просто по определению.
Это позволяет писать программы без ошибок?
Да, позволяет существенно снизить их количество.
Как выясняется, под программой понимается не приложение, а кусок кода, который ничего не делает или считает ряд Фибонночи.
Кем выясняется? Кто выяснить успел?
Это позволяет писать код яснее и короче? Приведённые примеры - что-то инопланетное, из них вообще невозможно понять, что происходит, как это отлаживать и как поддерживать.
Что вам в соседнем коде с
+
и*
непонятно?Как подсчитать определитель у определённой таким образом матрицы - непонятно. Из лемма Йонеды это никак не следует.
Если вы не смогли прочитать прямо написанное утверждение о том, что возможность категориальной формулировки матриц не означает, что надо обмазываться теоркатом, то определители вам считать ещё рано.
Олсо, exterior algebra спасёт отца
русской демократиивсплывающих подсказок в JavaFX. Которая, в отличие от вашего вузовского метода «ну ээээ по минорам тут раскладываем», обобщается до потребностей физиков с их физическими теориями (чё-то там про ОТО, струны, суперсимметрии, вот это всё — я в этих приложениях не настолько шарю, чтобы говорить что-то определённое).
RikkiMongoose
06.11.2024 14:00Да хоть тот же ghc, например.
То есть в компиляторе всё того же Haskell.
Market cap у какого-нибудь cardano, где это используется — 14 миллиардов, входит в топ-10
А почему не Hamster Combat? У него тоже была большая капитализация.
Или в гитхабе для анализа исходников.
Где я могу увидеть этот анализатор? На каком языке он написан?
Или в фейсбуке антиспам.
Я помню, как фейсбуковский антиспам не мог ничего сделать против одного отморозка, который призывал к убийствам и в каждый комментарий вставлял картинку.
Антиспам гордо рапортовал, что на картинке не обнаружено ничего плохого...
Мощная система. И что, тоже на Scheme написана?
Если вы не смогли прочитать прямо написанное утверждение о том, что возможность категориальной формулировки матриц не означает, что надо обмазываться теоркатом, то определители вам считать ещё рано.
Ну то есть вы не знаете, как считается определитель.
Этому обучают на профильных факультетах. Примерно на первом курсе.
обобщается до потребностей физиков с их физическими теориями (чё-то там про ОТО, струны, суперсимметрии, вот это всё — я в этих приложениях не настолько шарю, чтобы говорить что-то определённое).
Если не шарите - попробуйте восполнить оскорблениями. Расскажите им про помойных червей и обезьянок в зоопарке. Они будут вас внимательно слушать.
illinav
06.11.2024 14:00Как успехи с запретами состояний в ФП? Всё так же запрещено, или берёте свои слова назад?
То есть в компиляторе всё того же Haskell.
Да, который, в свою очередь, используется в куче упомянутых ниже приложений. Чем плохо?
А почему не Hamster Combat? У него тоже была большая капитализация.
А, то есть, теперь какие-то измеримые критерии вам не нужны? Ну понятно.
Где я могу увидеть этот анализатор?
Внутри кодовой базы гитхаба. Вероятно, для этого нужно туда устроиться.
На каком языке он написан?
На хаскеле.
Я помню, как фейсбуковский антиспам не мог ничего сделать против одного отморозка, который призывал к убийствам и в каждый комментарий вставлял картинку.
У вас аргументы всё мощнее. А я помню, как LLM рекомендовала пользователю пиццу с клеем, или что-то такое. И что теперь это говорит об ООП, с использованием которых по-вашему сделаны LLM?
И что, тоже на Scheme написана?
Не, я хаскелист, все мои примеры — на хаскеле.
Ну то есть вы не знаете, как считается определитель.
Как вы сделали этот вывод из моих слов? Или это открытая вами теорема, доказательство которой — ненужная мелочь?
Если не шарите - попробуйте восполнить оскорблениями. Расскажите им про помойных червей и обезьянок в зоопарке.
Зачем? Я же не @RikkiMongoose, чтобы всерьёз использовать «удручающе напоминает» как аргумент (и, тем более, единственный аргумент). И я даже не считаю, в отличие от вас, что их теории не допускают существования мира или прочий подобный очевидный бред, или что они не нужны, потому что тырпрайз струны перекалибровка, и вообще они разрабатываются случайными людьми в случайных институтах.
RikkiMongoose
06.11.2024 14:00Да, который, в свою очередь, используется в куче упомянутых ниже приложений. Чем плохо?
Тем, что gcc используется несколько шире.
А, то есть, теперь какие-то измеримые критерии вам не нужны? Ну понятно.
Заявления каких-то компаний и базворды в их отчётах - так себе аргумент. И тем более их капитализация.
По вашему нет компаний с большей капитализацией, которые используют Visual Basic?
Внутри кодовой базы гитхаба. Вероятно, для этого нужно туда устроиться.
Ну то есть вы предполагаете, что она там есть.
А я предполагаю, что там С++. Или Go. Или Rust. Или Visual Basic. Попробуйте опровергнуть.
У вас аргументы всё мощнее. А я помню, как LLM рекомендовала пользователю пиццу с клеем, или что-то такое. И что теперь это говорит об ООП, с использованием которых по-вашему сделаны LLM?
Это говорит о том, что никакой "защиты от ошибок" в Хаскелле нет. Раз один городской сумасшедший смог её обойти самым примитивным способом.
Как вы сделали этот вывод из моих слов? Или это открытая вами теорема, доказательство которой — ненужная мелочь?
Если вы не знаете, как аргументированно опровергать - попробуйте изучить учебник логики для первого курса.
А то как-то обидно получается - рассуждаете о доказательной теории и алгебре, а аргументировать только помойными червями умеете.
illinav
06.11.2024 14:00Ответ на вопрос про запрет состояний будет, или всё, энтузиазм демонстрировать своё широчайшее незнание ФП сдулся, и теперь будете стыдливо замалчивать?
Тем, что gcc используется несколько шире.
Интересно! Все приложения, которые используются не так широко, как gcc, теперь не нужны?
Заявления каких-то компаний и базворды в их отчётах - так себе аргумент.
Но хаскель же никому не нужен, как это может быть баззвордом? Впрочем, это и неважно, потому что это рыночная капитализация. Понимаете, почему это, ну, не заявления-баззворды?
Кстати, какие у вас есть пруфы регулярного ежедневного использования LLM? Без баззвордов и заявлений в отчётах плз.
Ну то есть вы предполагаете, что она там есть.
Я знаю, что она там есть, потому что я туда собеседовался на позицию хаскель-разработчика, и я прямо обсуждал с интервьювером, что предлагается делать.
А я предполагаю, что там С++. Или Go. Или Rust. Или Visual Basic. Попробуйте опровергнуть.
Зачем? Я же не выдаю утверждения уровня «в Go нет возможности написать цикл, потому что он нигде не используется».
Это говорит о том, что никакой "защиты от ошибок" в Хаскелле нет. Раз один городской сумасшедший смог её обойти самым примитивным способом.
Вы серьёзно уравниваете защиту от ошибок уровня, упрощая, «обратиться по нулевому указателю» или «параллельно модифицировать объект из двух разных потоков» или «объект нарушает собственные инварианты, если перед вызовом метода
string GetName()
не вызватьvoid CalculateSalary()
», и алгоритмически-бюрократические наблюдаемые эффекты системы для стороннего наблюдателя? Возможно, это вообще было в рамках ожидаемого поведения для заданной fpr/tpr, но вам удобнее предполагать, что есть какая-то ошибка, не так ли?Если вы не знаете, как аргументированно опровергать - попробуйте изучить учебник логики для первого курса.
То есть, вы ляпнули какую-то ерунду, никак не вытекающую из слов собеседника, а теперь требуете от него её опровергать. Кому тут учебник нужен и чего?
А то как-то обидно получается - рассуждаете о доказательной теории и алгебре, а аргументировать только помойными червями умеете.
Обидно получается, когда всё время в качестве аргументов используешь «удручающе напоминает величайшие теории Фоменко и никому в жизни не нужные примеры интегралов из учебников», а когда получаешь наглядную иллюстрацию, почему так делать не надо, скуксиваешься и начинаешь кричать как на базаре «караул! грабят! оскорбляют!!»
RikkiMongoose
06.11.2024 14:00Если бы вы разбирались в теме, то аргументация звучала бы так:
Scheme и чисто функциональные языки активно применяются в области X. Да, они не подходят для программирования контроллеров, но пример современного использования можно найти в книге Y.
Для примера: вот код, который описывает математическую матрицу средствами Haskell. После того, как вы определили матрицу таким образом, вы можете легко производить над ней операции вот так:
Я допускаю, что вам интересно рассказывать про лемму Йонеды. Но вот что важно: вас про лемму Йонеды и капитализацию криптовалют никто не спрашивал.
Так что я не берусь вам ничего объяснять - потому что мне очевидно, что вы ничего из моих объяснений не поймёте. Вы - гений, вы знаете лемму Йонеды. Нам всем остаётся только внимать такому великому гению, как вы.
illinav
06.11.2024 14:00Понятно, значит, энтузиазм с рассказами про детали работы ФП у вас действительно сдулся. Зачем вам надо было изначально строить из себя эксперта, если вы в теме не разбираетесь от слова совсем?
Если бы вы разбирались в теме, то аргументация звучала бы так
Для того, чтобы приводить какую-то аргументацию, она должна быть в тему (которую вы, конечно, пытаетесь всё время изменить и игнорируете исходную). Тема обсуждения — как в ФП выражать состояние (ну, то, что вы утверждали как что-то невозможное). По этой теме я дал вам ссылки на ключевые слова в самом начале — чтобы вы могли сами выбрать, читать вам книги, где эти слова есть в оглавлении, или wikibooks, или документацию на эти вещи, или любой из множества постов в каких-нибудь блогах, или, в конце концов, спросить у меня конкретные ссылки-рекомендации.
Вы же выбрали самый лучший путь узнать что-то новое и ликвидировать своё незнание после того, как опростоволосились: начать рассказывать, что эти вещи не имеют значения, потому что случайные проекты в случайной академии рядов фибиначи. И именно поэтому я сказал про в том числе
капитализацию криптовалют
и многие другие области применения, которые как раз и являются этим самым
пример[ом] современного использования
который вы так хотели.
Более того, если бы вам действительно было интересно обсудить
код, который описывает математическую матрицу средствами Haskell
(что, отмечу, было упомянуто вообще в другой ветке, к теме нашего разговора отношения не имеющей), то вы могли бы ответить на мой совершенно нериторический вопрос (заданный вам несколько комментариев назад)
Что вам в соседнем коде с
+
и*
непонятно?что-нибудь в духе «покажите, как это выглядит в более крупном примере». Вы же выбрали напрочь проигнорировать эту ветвь разговора, а теперь предъявляете мне претензию, что я вам не привёл более крупный пример.
Но вот что важно: вас про лемму Йонеды
…которая была в другом обсуждении и как иллюстрирующий пример, что возможность выразить что-то в определённом формализме не требует выражать это именно в нём — что вы не способны осознать до сих пор.
и капитализацию криптовалют
…что, ещё раз, является прямым ответом на ваши слова о том, что это не вылезает за пределы случайных проектов и академий.
никто не спрашивал.
Вот чего точно никто не спрашивал — вашего очень ценного мнения о том, что вам удручающе напоминают те или иные вещи. Но это ведь не мешает вам его высказывать, более того, высказывать как единственный [псевдо]аргумент, не так ли?
Так что я не берусь вам ничего объяснять - потому что мне очевидно, что вы ничего из моих объяснений не поймёте.
Вы не берётесь объяснять потому, что все ваши объяснения — это отсылки к тому, что те или иные вещи вам удручающе напоминают, и псевдоаргументы уровня «ФП запрещает состояние, потому что если бы разрешало, то им бы пользовались чаще, чем gcc».
illinav
06.11.2024 14:00По теме я написал в самом начале, вы же решили перевести разговор на личности. Ну, enjoy.
ednersky
06.11.2024 14:00слушайте, вы настолько точно изложили МОЮ точку зрения, что Вам огромное сердечное спасибо! Прям в закладки добавлю и буду ссылку давать на этот текст, когда очередной раз увижу выступление о монадах :)
illinav
06.11.2024 14:00А есть что-то такое, но про ООП? А то вы выше выступали про объекты, про паттерны, про фабрики, про синглтоны, вот это всё, а как включаешь — не работает. Написана куча книг, куча людей сделала имя, Дядя Боб самый авторитетный авторитет, а включаешь — не работает. В какой проект ни глянь — месиво из абстрактных фабрик декораторов фасадов, куча книг про head first patterns, каждый пытается объяснить SOLID, и по своему. а включаешь — ну, вы поняли.
ednersky
06.11.2024 14:00ХЗ, ООП работает в каждой первой программе.
если про него что-то и есть, то как с той демократией по Черчиллю: "демократия плоха, но на сегодня все прочие варианты хуже" (цитата по памяти)
illinav
06.11.2024 14:00Открыл упомянутый рядом gcc — там нет всех этих абстрактных фабричных методов. Открыл кодовую базу okular, в котором я сейчас читаю книжку — там файл на 5000 строк, отвечающий за всё, и никакого разделения уровня GoF. Много работал с eigen — прокси-синглтонов фабрик там тоже нет.
Да и в соседнем посте мне доказывали, что настоящий ООП только во всяких смоллтолках, а в этих ваших C++/java/c# так, пародия от неосиляторов. И где этот ваш смоллтолк? Там же, где ООП.
ednersky
06.11.2024 14:00я ХЗ что там в смолтолках, а пример ООП есть даже в простом банальном Си - вот этот вот указатель FILE * и всякие fopen, fclose с ним связанные.
vadimr Автор
06.11.2024 14:00Люди, которые придумали FILE*, fopen и fclose, такого слова-то, как ООП, не знали. Его не придумали ещё тогда.
FILE* – это адрес в памяти дескриптора файла.
ednersky
06.11.2024 14:00такого слова-то, как ООП, не знали. Его не придумали ещё тогда
https://music.yandex.ru/album/6540763/track/48023853
Извините, не удержался
illinav
06.11.2024 14:00я ХЗ что там в смолтолках
Там всё —
файлобъект, и всему можно посылать любые сообщения. Позднее связывание (позднее некуда), полиморфизм, вот это всё, ну и слова Алана Кея про «когда я придумывал демократию, я точно не имел в виду C++».а пример ООП есть даже в простом банальном Си - вот этот вот указатель FILE * и всякие fopen, fclose с ним связанные.
Окей. А тогда можете привести пример языка сложнее брейнфака, где не было бы ООП?
ednersky
06.11.2024 14:00а нет такого языка.
даже на лиспе если начать описывать те же матрицы, то снова получится ООП
ednersky
06.11.2024 14:00я вообще говорил о том, что поскольку нас окружают различные объекты, то отвергать ООП неправильно. В этом будет причина (одна из причин) непопулярности языков чисто ФП.
ведь то, что ООП на чисто ФП языках довольно сильно затруднён - факт.
illinav
06.11.2024 14:00Мы же с вами уже выяснили, что ООП есть в любом языке, позволяющем создавать типы и операции над ними (что бы это ни значило), поэтому ООП есть и в чисто ФП языках, покуда там есть система типов.
Какие языки отвергают ООП?
ednersky
06.11.2024 14:00Там всё —
файлобъекткстати, может быть именно поэтому смолтолк и план9 не обрели свой успех?
берём любую (ЛЮБУЮ!) вещь, хоть ООП, хоть ФП, хоть фанатство к файлам. Доводим её до абсолюта и вот вам... совершенно ненужная хрень на выходе.
Там, где ООП не нужен, он, разумеется, не нужен.
Там где нужно ФП, оно, разумеется, нужно.
ну а современные популярные языки позволяют И то И другое, а при необходимости поставить ИЛИ - можно ставить ИЛИ
illinav
06.11.2024 14:00ну а современные популярные языки позволяют И то И другое, а при необходимости поставить ИЛИ - можно ставить ИЛИ
Так
FILE*
— это же тоже ООП. И вообще любой современный язык, включая хаскель и coq, позволяют ООП. В чём проблема?
RikkiMongoose
06.11.2024 14:00У меня всё это вызвало стойкое ощущение, что перед нами - эпические усилия по изобретению колеса.
Вот что делает код:
команда пуэп 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-х.
vadimr Автор
06.11.2024 14:00Этот код ничего не ДЕЛАЕТ. Он говорит о том, что в протоколе работы с устройством "пуэп" есть собственная команда этого устройства с кодом 64, которую мы называем "ошибка", имеющая девять выходных параметров определённых типов.
Просто декларативное описание протокола работы.
Можно написать, например,
(команда http "GET" get istr ostr)
и будет автоматически сгенерирован код простейшего веб-браузера.
Записать это, конечно, можно в любом виде, но предложенные вами в данном примере 5 типов синтаксических разделителей для выражения простой мысли выглядят чудовищно.
RikkiMongoose
06.11.2024 14:00и будет автоматически сгенерирован код простейшего веб-браузера.
А поддержка 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;|
Какой-то плохой браузер получился. Мне не подходит.
vadimr Автор
06.11.2024 14:00А поддержка JavaScript в этом браузере будет?
Ну извините, бесплатно – берите что дают. Без джаваскрипта.
Я вот специально зашёл на https://try.scheme.org/и вбил в строку выполнения
(команда http "GET" get istr ostr)
Так вам ещё нужен весь остальной код программы, чтобы такая команда работала.
Здесь от базового синтаксиса Scheme только строковый литерал "GET".
illinav
06.11.2024 14:00Кажется, кто-то только что изобрёл Observer, Command и Strategy.
Кто-то изобрёл Interpreter
Что значат все эти слова?
Указатели на функции были ещё в C.
Указатели на функции сами по себе не позволяют связывать с ними данные, и не позволяют создать внутри функции новую функцию и вернуть указатель на неё.
Давно есть даже в C++.
Не давно, а всего-то 13 лет, при этом полиморфные лямбды — 10. И при этом они туда перекочевали именно из ФП.
Требования писать функции чисто и по возможности использовать иммутабельность - были ещё в учебниках 1980-х.
А в случае типизированного ФП (и ИМХО обсуждать другой смысла нет) она в системе типов.
RikkiMongoose
06.11.2024 14:00Что значат все эти слова?
Начальное представление о значении этих слов можно получить в Википедии
illinav
06.11.2024 14:00То есть, вы не знаете, но надуваете щёки. Это вообще очень показательное поведение для сторонника ООП, ведь главное — надуть щёки посильнее на ближайшем аджайл-стендапе, сказав «я проектирую стратегию интерпретации команд для обсёрвера». На практике это не работает, потому что это не используется вообще нигде, даже в gcc.
</RikkiMongoose>
RikkiMongoose
06.11.2024 14:00Судя по издевательскому тону, в котором вы их уже упоминали, вы что-то слышали о паттернах проектирования. Можете посмотреть подробности о них в оригинальной книге (она так и называется - "Паттерны проектирования")
qandak
06.11.2024 14:00Для Haskell есть даже сервис поиска функций по сигнатуре (!) в библиотеках по всей репозитории. А библиотек там, поверьте, не мало. Для подключения к Postgres - не менее дюжины, с примесями ОРМ и без. Там и свой crates и cargo и вся инфраструктура есть давным давно (кроме отдельного IDE). Но вроде ситуация от этого не меняется.
ednersky
06.11.2024 14:00ну, зато полезные приложения на хацкеле я встречал: один из оконных менеджеров, например, ну и архиполезнейшая хреновина - pandoc.
может быть, именно потому они и существуют, что упомянутую оснастку для этого языка сделали?
qandak
06.11.2024 14:00Это называется "не прочитал, но своё мнение я скажу". Так и я об этом же - инфраструктура есть, но популяризации она не способствует.
illinav
06.11.2024 14:00не очень понимаю, почему ФП подходит исследователю лучше, чем не ФП.
Исследователь он что делает?
Смотря какой исследователь. Если это исследователь машинного зрения на таких-то технологиях, то ему полезнее язык, где есть удобные байндинги к opencv, или готовые описания нейросеток из статей с последнего nips.
Если это исследователь языков программирования или определённого класса алгоритмов, то ему удобны ML-подобные языки вроде хаскеля или вообще агды.
Если это исследователь-квант (ну, quantitative trader, их почему-то иногда тоже исследователями называют), то он вообще может на плюсах писать или на матлабе.
Ну например пытается "зрением" некоего робота оснастить.
Это вообще звучит уже как куда ближе к чистой инженерии, а не к исследованиям.
c0r3dump
06.11.2024 14:00Что конкретно исследуют эти инженеры при помощи scheme и где познакомиться с результатами?
illinav
06.11.2024 14:00Например, поверх racket (который является одним из диалектов scheme (но я не схемер (поэтому не факт, что диалектом (это лучше у схемеров спрашивать)))) сделан целый тулбокс plt/redex для языковых инженеров, и написана целая книжка «semantics engineering with plt/redex», этак половина которой отводится на изучение конкретных случаев использования этого тулбокса, включая достаточно прикладные задачи типа «разработки языка для описания опросов для исследований по психологии, который давал бы такие-то гарантии построения зависимых многошаговых форм».
RikkiMongoose
06.11.2024 14:00Удручающе напоминает "великую теория Смысл-Текст" Мельчука и Жолковского. В ABBYY на её основе лет 10 делали систему автоматического перевода - и так и не сделали.
illinav
06.11.2024 14:00О, до чего техника дошла, вас и тут и там в разных тредах показывают! И в обоих тредах у вас основной аргумент — «удручающе напоминает».
Серьёзный, мощный аргумент. Кому-то ООП (или ваш любимый мейнстримный язык, или что угодно) удручающе напоминает обезьянок в зоопарке, которые коровьими лепёшками перекидываются, и что?
RikkiMongoose
06.11.2024 14:00Однако на ООП реализовано множество приложений, которыми мы пользуемся каждый день. В том числе и языковых моделей.
В то время как другие были заняты изучением обезьянок в зоопарке. Возможно, как раз для этой важнейшей задачи Scheme и является крайне востребованным языком.
illinav
06.11.2024 14:00Удручающе напоминает хайп с биткоинами. Я каждый день пользуюсь банковской карточкой, обслуживаемой 60-летней кодовой базой на коболе, а LLM-ки удручающе напоминают чатботы из ранних нулевых.
RikkiMongoose
06.11.2024 14:00Предлагаю вспомнить ещё один успешный проект на Racket - Perl 6.
Им тоже никто не пользуется.
illinav
06.11.2024 14:00Удручающе напоминает perl 5 и удручающие cgi-скрипты из поздних девяностых и ранних нулевых.
RikkiMongoose
06.11.2024 14:00Тем не менее Perl 5 продолжает обновляться и у него на порядок больше пользователей.
Очевидно, он позволяет решить больше задач и более удобен.
illinav
06.11.2024 14:00Удручающе напоминает копошение червей у прорвавшегося мусорного пакета.
Смотрите, я тоже могу удручающе напоминать!
RikkiMongoose
06.11.2024 14:00Вам стоило бы немного поизучать логику. Аргументация оскорблениями (то у вас обезьянки в зоопарке, то копошение червей у мусорного пакета) - признак небольшого ума.
illinav
06.11.2024 14:00Лол.
Я прямо в первом ответе вам написал, что отсылка к «удручающе напоминает». которой вы пользуетесь регулярно как аргументом, этим самым аргументом не является. В первом же ответе я написал, что кто-то (сиречь не я, и я это как аргумент не использую) может тоже иметь удручающие воспоминания от ООП, и мой последующий вопрос «и что?» мог бы вам намекнуть, что я это аргументом не считаю, и вас призываю не считать, а выделение курсивом могло бы намекнуть на отсылку к вашему использованию этих слов.
Более того, моя фраза «Смотрите, я тоже могу удручающе напоминать!» в последнем комментарии тоже могла бы вам намекнуть, что я по-прежнему не считаю это аргументом, и что моя цель — наглядно показать вам, что это аргументом не является и являться не может.
Но это всё прошло мимо вас, поэтому, пожалуйста, воспользуйтесь собственным советом и изучите хоть немножко логику сами.
Я уж не говорю о том, что апеллировать к тому, что вас тут типа как оскорбили, с конкретно вашей стороны особенно сочно.
RikkiMongoose
06.11.2024 14:00Обратитесь к обезьянкам в зоопарке и к помойным червям. Вы явно эксперт в этой области, они с удовольствием вас послушают. Уверен, вы просто раздавите их вашим космическим интеллектом.
illinav
06.11.2024 14:00Ну понятно, мастеру по оскорблению окружающих («великая теория Смысл-Текст», «К сожалению, мне нет дела до того, какие слова или выражения вы выучили») и псевдоаргументам («удручающе напоминает» и, в общем, в среднем этак две трети ваших комментариев) не понравилось, когда ему наглядно показали, как выглядит его метод ведения дискуссии.
Ожидаемо, но скучно.
RikkiMongoose
06.11.2024 14:00Скажем так - этот язык появился раньше Perl и с тех пор особо не развился. Никаких преимуществ перед JavaScript не обнаружено.
RikkiMongoose
06.11.2024 14:00Невероятные технологии из 1985 года.
Возможно, в следующей статье нам расскажут про язык макросов в C.
А так, конечно, после волны скриптовых языков начала 90х всё это уже не актуально. В JavaScript уже в 2000 году были и деревья, и функции как значения и даже eval.
vadimr Автор
06.11.2024 14:00Что характерно, это пишет человек, написавший статью про программу из 200 строк для корректного сравнения объектов в JavaScript :)
Причём программа-то хорошая и нужная, но вот 200 строк на примитив equal? - нужен ли нам такой 2000 год?
RikkiMongoose
06.11.2024 14:00Ну, за 10 лет прошедшие с написания той заметки я несколько вырос - а Scheme неизменен с 1985 года.
vadimr Автор
06.11.2024 14:00Последний стандарт Scheme принят в 2013 году, SRFI – в 2023. Подозреваю, что за это время универсальное средство сравнения объектов в джаваскрипте так и не появилось, потому что джаваскрипт вообще – антипаттерн проектирования ЯП.
RikkiMongoose
06.11.2024 14:00И как новый стандарт SRFI повлиял на популярность языка? Fortran тоже в 2018 году обновился.
Сравнивать в JavaScript сложнее, чем в Scheme, потому что в JavaScript не все типы сводимы к деревьям. А так-то готовые методы есть в underscore и lodash.
Вообще, JavaScript наглядно доказывает, что языки программированяи бывают двух видов: на одни все жалуются, а другими никто не пользуется. Lisp-оподобные языки были популярны как скриптовые языки в больших системах (с тех времён уцелели Emacs, Mathematica, Gimp) в те времена, когда документации было мало и разработчику приходилось работать лексером и парсером. Но почему-то как только появились Perl, а потом Python, Ruby, JavaScript и Lua, именно их, при всех недостатках, стали понимать интерпретаторы.
За 10 лет функционального ренессанса так и не случилось. А всё, что действительно было нужно, давно перенесли в мейнстримовые языки.
vadimr Автор
06.11.2024 14:00Фортран обновился в 2023 году и активно используется в своей области, входя в десятку наиболее используемых ЯП.
Scheme не является скриптовым языком. Это компилируемый (при необходимости) язык программирования высокого уровня.
RikkiMongoose
06.11.2024 14:00Ну вот видите. Язык прошёл проверку временем. В отличии от Scheme.
Судя по той же таблице популярности, Scheme - это эзотерический язык где-то между Closure и Brainfuck
qandak
06.11.2024 14:00Ваши представления о языках ФП тоже немного подустарели.
Clojure (кстати, тоже Лисп) не более "эзотерический" в 2024, чем, скажем, Ruby, если исключить большее количество легаси из-за старости второго. Можете ознакомиться со списком компаний использующих Clojure, от Apple до Netflix. Популярная графовая БД Datomic тоже полностью написана на Clojure.
RikkiMongoose
06.11.2024 14:00Closure в 2024 достаточно эзотеричен, чтобы на него почти полностью отсутствовали вакансии. C 2007 года его много где могли попробовать, но в отличии от PHP и JavaScript, не нашлось ни одной области, где он бы обеспечил хоть какое-то преимущество над более простыми решениями.
nim и Nemerle тоже где-то пробовали. А на Lotus до сих пор что-то в каких-то компаниях работает.
qandak
06.11.2024 14:00Почти полностью отсутствуют вакансии где, в России?
C 2007 года его много где могли попробовать
А почему попробовать должны были именно там, где вы ожидали? Я же привел примеры и ссылку.
PHP незаменим из-за охренительного количества легаси. Javascript, как рантайм - из-за браузера, а как язык оказался хуже, чем десятки надстроек над ним. И ClojureScript, как бы иронично не звучало, один из них.
RikkiMongoose
06.11.2024 14:00У меня https://clojurejobboard.com/ открылся как пустая страница.
Замечательная демонстрация продвинутости технологии и профессионализма тех, кто её использует.
vadimr Автор
06.11.2024 14:00Так страница написана на джаваскрипте.
Сколько я ни знал программистских контор, ни у одной не было достаточно денег, чтобы платить самой себе за свой собственный корпоративный вебсайт. Всегда заказывали на стороне.
vadimr Автор
06.11.2024 14:00Так и Лисп не эзотерический язык. Clojure нормальный диалект Лиспа, только поверх JVM. Могу понять людей, которым не хотелось писать на Джаве, когда они знают Лисп.
RikkiMongoose
06.11.2024 14:00Могу понять даже людей, которые пишут на кроссплатформенном и Тьюринг-полном языке Brainfuck.
Avatap
06.11.2024 14:00Вы говорили про отличия от лисп а есть ли в ским библиотека по типу cffi для интеграции сишного кода? Если есть то вопрос о недостатке библиотек не слишком актуален :)
vadimr Автор
06.11.2024 14:00Библиотеки такие есть на уровне конкретных реализаций. Но надо ж понимать, что потенциальная возможность подключения сишного кода – это не то же самое, что взял и использовал библиотеку. Надо изучить сишный прототип функции, подготовить параметры сишных типов, обеспечить некий общий контекст, и в общем каждый вызов функции на другом языке обычно превращается в танцы с бубном (это не только для лиспа справедливо).
В этом плане интересная работа проводится в Gambit Scheme (я привёл ссылку на лекцию в статье), где прямо посреди скимовского кода можно писать императивные операторы с питоновскими вызовами чего угодно. И автор прямо в видео показывает, как он pip'ом какую-то там полезную примочку подтянул и тут же из скима вызвал. Тем более, к питону концептуально проще цепляться, чем к си – он тоже динамический язык.
Я, правда, не пробовал этим пользоваться – там надо для начала перекомпилить сам Gambit в другом режиме, а я боюсь в это ввязываться, так как может пострадать стабильность работы. Имея в прошлом большой опыт организации связей между программами на разных языках и задав сам себе вопрос, готов ли я из-за пары питоновских функций получить возможную трудноуловимую ошибку, я понял, что лично я – не готов. Но кому-то может быть полезно.
Я лично в целом сторонник микросервисной архитектуры, и считаю, что, по большому счёту, если сокеты есть (а они в скиме есть на уровне конкретных реализаций) – то уже жить можно.
ednersky
06.11.2024 14:00поскольку дискуссия пошла несколько "не туда", предлагаю ещё одну веточку
я вот вижу неплохие перспективы LISP на поприще реализации интерпретаторов каких-то языков программирования.
Вот, скажем, нужен нам э... ну аналог Lua в э... ну пусть будет Rust.
Вот берём мы и пишем парсер этого самого Lua, а результат парсинга сводим к виртуальной машине работающей с S-выражениями. Потом по этим S-выражениям ходит условная (подчёркиваю - условная) LISP-машина.
Так вот, в этом месте возникают вопросы "взять готовую LISP машину и встроить к себе в проект на C/Rust/Go/брейнфак".
Можете что-то об этом сказать?
vadimr Автор
06.11.2024 14:00Мысль Ваша движется в правильном направлении.
Более того, на сегодня подавляющее большинство компиляторов использует в качестве промежуточного представления кода программы AST деревья, которые по сути являются специализированным диалектом Лиспа. Так что можно сказать, что программа на Rust фактически сначала транслируется в Лисп (AST дерево) фронтендом компилятора, а потом уже бекенд компилятора транслирует AST дерево в машинный код.
И одно из применений языков Lisp и Scheme – это как раз скрипты для прикладных программ. Например AutoCAD скриптуется на AutoLisp, GIMP – на TinyScheme. Это также к вопросу об обработке изображений.
ednersky
06.11.2024 14:00Так что можно сказать, что программа на Rust фактически сначала транслируется в Лисп (AST дерево) фронтендом компилятора, а потом уже бекенд компилятора транслирует AST дерево в машинный код.
это-то я понимаю, но я хочу пользу от именно scheme заполучить. то есть я хочу вместо libast.so (который в общем виде придётся по большей части писать самому) использовать libscheme.so, который условно говоря "готов" и позволяет реализовать built-in функции моего языка не на C/Rust/Go, а прямо на scheme/lisp.
RikkiMongoose
06.11.2024 14:00В принципе, задача решена в книге Writing an Interpreter in Go (только для Go). Там пишут JS-подобный язык (даже с макросами) и спокойно обходят эти S-выражения.
Аналогично есть уже нативные:
ednersky
06.11.2024 14:00э... вы не совсем поняли мой вопрос.
смотрите, я пишу интепретатор нового (или старого - не важно) языка.
что мне для этого нужно?
распарсить всё в токены,
упорядочить те токены в правильном порядке (вот здесь где-то и получится набор s-выражений)
выполнить те s-выражения какой-то машиной
и вот если с первыми двумя задачами прекрасно справится какой-нибудь аналог yacc, то если я возьму для третьей какую-либо LISP-машину, смогу ли себе сэкономить в разработке.
типа к LISP-машине я буду приписывать библиотеки на LISP'е
типа используя LISP-машину я не пишу свою VM
в этом месте интересно использование той Scheme/LISP как э... встраиваемой функции, вызываемой из libfoobar.so. Настройка этой libfoobar на использование того или иного метода управления памятью (при встраивании хорошо бы иметь единообразную систему и там и тут) и интеграцию, скажем, с асинхрой/процессами итп.
есть хауту на эту тему?
RikkiMongoose
06.11.2024 14:00В уже указанной книге написанию такого интерпретатора на 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
vadimr Автор
06.11.2024 14:00На мой взгляд, использовать yacc вне контекста написания компилятора – очень мощное извращение. Всё-таки расписывание контекстно-зависимой грамматики – это не то, чем обычно хочется заниматься в жизни.
Лисп сам по себе не является виртуальной машиной. Это просто формализм для синтаксиса и семантики, при необходимости расширяемых пользователем. Если вас устраивает базовый синтаксис Лиспа в виде S-выражений, то поверх него вы можете реализовать только макросами и функциональными формами какой угодно конечный язык. Если же S-выражения вас интересуют только как промежуточная форма представления данных, то вряд ли вы на этом сможете что-то выиграть от использования интерпретатора Лиспа.
RikkiMongoose
06.11.2024 14:00Говоря проще, LISP - это JSON с макросами.
vadimr Автор
06.11.2024 14:00Нет, потому что Лисп – это как данные, так и имеющий определённую семантику код, а JSON – только данные.
ednersky
06.11.2024 14:00Если же S-выражения вас интересуют только как промежуточная форма представления данных, то вряд ли вы на этом сможете что-то выиграть от использования интерпретатора Лиспа.
я рассчитывал, что в этом случае, можно ПЕРЕиспользовать кем-то написанный на LISP'е код для реализации built-in функций нового языка.
вот, например, sort. Так или иначе он есть в любой стандартной библиотеке языка.
если мы пишем новый язык и берём свой интерпретатор s-выражений, то эту самую сортировку придётся ваять или на этом новом языке или на С/Rust (или на чём мы там пишем) или написать её прямо на уровне s-выражений.
если на уровне этих выражений LISP, то появляется шанс взять что-то готовое.
то есть я воспринимал это так.
vadimr Автор
06.11.2024 14:00Ну смотрите, в языке же всё завязано одно на другое.
sort-list в Scheme – это функция высшего порядка, у которой первым аргументом идёт лямбда-выражение, задающее упорядочивающее отношение, а вторым аргументом список, который в Лиспе/Scheme тоже реализуется вполне определённым образом. В стандартном Лиспе заодно ложь и пустой список – одно и то же значение. То есть вам надо построить лисповские структуры данных, чтобы обрабатывать их лисповскими функциями.
Мы же программируем, наверное, не альтрнативную синтаксическую обёртку над функциями Лиспа (что довольно бессмысленно), а новый язык со своей собственной семантикой. А если брать функции Лиспа, так надо не выпендриваться, а записывать их вызовы на Лиспе.
ednersky
06.11.2024 14:00тогда ниша лиспа остаётся только в учебном смысле. я больше пока не вижу, где его можно применять.
если мы говорим об инженере-исследователе, то ему лучше использовать какой-то язык ВЫСОКОГО уровня (LISP я бы назвал языком низкого уровня, именно из-за отсутствия многих эксплуатационных/тулзовых вещей)
типа "если вы хотите понимать, как работает VM практически любого языка, то вот вам пример". Не более того.
PS: emacs вроде бы на лиспе написан.
поскольку это очень большой проект, то из него можно было бы выделить какие-то компоненты в libfoobar.so и использовать в других программах. Ту же работу с клавиатурой, с терминалом, с Xorg, итп.
Не знаете, что-то такое есть в природе?
vadimr Автор
06.11.2024 14:00Лисп язык очень высокого уровня, и именно поэтому в нём нет эксплуатационных/тулзовых вещей. Он выше их уровнем.
Сам я использую Scheme для реализации некоторого метаязыка – надстройки над сервисами, написанными на других языках. А всякие базы данных, GUI интернет и прочее – они ниже уровнем, в условном “ассемблере”. Фактически я имею возможность давать описание задачи компьютеру на языке, приближенном к естественному, а программа на Scheme сама преобразует их семантику к операциям, исполняемым при помощи других прикладных программ, и сама генерирует для этого код.
А VM ко всему этому вообще не имеет никакого отношения. Лисп – компилируемый (при необходимости) в машинный код язык.
ednersky
06.11.2024 14:00Он выше их уровнем.
это субъективизм вида схожего с "человек королевских кровей выше прочих уровнем".
почему? потому что королевских кровей.
vadimr Автор
06.11.2024 14:00Это объективная картина, потому что семантика Лиспа, построенная на базе аппарата лямбда-исчисления, позволяет повышать уровень абстракции неограниченно. В то время как в мейнстримных языках программирования мы всегда ограничены их базовыми конструкциями.
Конечно, можно сказать, что и объект может иметь сколь угодно сложное поведение, но всё равно мы остаёмся зажаты в тисках интерфейса между объектами. В то время как Лисп – это, в сущности, просто пустые формы со скобками, которые могут наполняться произвольной семантикой.
Можно сказать по-другому. Лисп позволяет непосредственно описывать денотационную семантику, а не только операционную, то есть его формы могут соответствовать онтологии предметной области, а не просто поведению программы.
ednersky
06.11.2024 14:00позволяет повышать уровень абстракции неограниченно
семантика ЛЮБОГО языка позволяет это делать.
взять например ASM. вы можете манипулировать словами и байтами, а можете оперировать объектами, содержащими объекты, содержащими объекты.
Конечно, можно сказать, что и объект может иметь сколь угодно сложное поведение, но всё равно мы остаёмся зажаты в тисках интерфейса между объектами.
ну а у LISP разве не так?
vadimr Автор
06.11.2024 14:00Так я как раз не хочу ничем оперировать. Или хочу оперировать как можно меньше.
ASM не позволяет делать утверждения, а Лисп позволяет. ASM просто задаёт команды.
Это, кстати, значительная проблема при обучении ФП людей, ранее знакомых с императивными языками – отучить их мыслить поведением.
ednersky
06.11.2024 14:00Так я как раз не хочу ничем оперировать. Или хочу оперировать как можно меньше.
так ведь это желание невозможно исполнить, если вы программируете что-то более-менее отлчиающееся сложностью от чисел Фибоначчи.
сложили числа в матрицу - появилось понятие матрицы и операторы, ей манипулирующие. и вот мы пришли к объектно-ориентированному программированию не уходя далеко от математики
при том, что в современном мире чаще всего понятия "математика" и "программирование" вообще не имеют точек пересечения.
ASM не позволяет делать утверждения, а Лисп позволяет.
чем макросы или функции - не утверждения?
vadimr Автор
06.11.2024 14:00Тут надо внимательно следить за руками. Хотя математика исторически и появилась как способ подсчёта отнимаемого у крестьян зерна, но в современном понимании не является манипуляцией с числами. И операторы над матрицей или функции в математике просто фиксируют отношения между правой и левой частями. Например, в математическом утверждении sin(x) = cos(x+pi/2) нет никакого вычисления или манипуляции, это просто денотация свойства синуса и косинуса.
В императивном же смысле функция понимается только как способ вычисления результата и выходных параметров по входным. И это несколько другое дело. Где немного другое, а где и очень сильно другое.
Если бы мы не умели вычислять значения синуса и косинуса, то фиг бы мы вообще что получили императивным способом определения функции из равенства sin(x) = cos(x+pi/2). Хотя как база для символьных преобразований – оно вполне рабочее.
Вообще же про математику лично я до сих пор ничего и не писал. Я занимаюсь системами управления, например.
ednersky
06.11.2024 14:00про математику очень много в книге, что рекомендуется в статье
там чуть ли не все программы что в примерах - вычисление каких-то математических значений.
поскольку там все примеры идут о простых числах (максимум простых чисельных рядах) а здесь был ответ "не хочу оперировать объектами" (в исходном сообщении "оперировать объектами", далее "не хочу ничем оперировать" я воспринял примерно в этом ключе), то я распространил простые примеры книги на чуть более сложный случай.
Извините, если, математику Вы в виду не имели.
vadimr Автор
06.11.2024 14:00Ну в книге в первых главах чисто учебные примеры. На математических вычислениях некоторые вещи проще объяснять, так как модель предметной области всем понятна.
ednersky
06.11.2024 14:00Это кстати проблема многих книг и собеседований: там примеры, которые среднему программисту НИКОГДА не встретятся.
Средний программист НИКОГДА не программирует ряды Фибоначчи, факториалы, биномы Ньютона. Никогда не опускается до разбора "что там за алгоритм сортировки под капотом stdlib" и так далее
vadimr Автор
06.11.2024 14:00Ну в таком случае эта книга для программистов выше среднего. Собственно, это действительно так, так как это учебное пособие для курса системного программирования в одном из ведущих мировых вузов.
RikkiMongoose
06.11.2024 14:00Важное уточнение - учебное пособие приблизительно 40 летней давности. С тех пор индустрия шагнула немного вперёд. И сам курс давно читают с примерами на Python 3.
vadimr Автор
06.11.2024 14:00Я бы сказал, что с тех пор уровень образования в колледжах США резко снизился, и студенты не могут осилить старый курс.
Новый курс вообще совсем поверхностный, а не то что просто переведён на Python.
А работают на умных должностях китайцы и прочие приезжие.
RikkiMongoose
06.11.2024 14:00Ну я бы сказал, что всё намного проще - с появлением более лаконичных и читаемых языков Scheme отправился вслед за Smalltalk и Simula67
RikkiMongoose
06.11.2024 14:00Эта книга - 1985 года. Тогда ещё даже Mathematica не было.
По сути же - системы доказательств и преобразований из формулы в формулу не особенно популярны за пределами узкого круга тех, кто разрабатывает Coq. Ещё Пуанкаре говорил, что великие математики открывают теоремы - а посредственные математики нужны, чтобы их доказывать.
Если вычислительная математика - то компьютер просто используется как очень мощный калькулятор, там LISP-ов нет, а используется C-подобная CUDA или даже Fortran (на суперкомпьютерах до сих пор). А логическая математика - это крайне узкая область и описание её объектов очень утомительно: приходится разворачивать каждое "после тривиальных преобразований получим". Гротендик и вовсе считал такие инструменты концом математики как науки.
ednersky
06.11.2024 14:00Я занимаюсь системами управления, например.
а в системах управления разве объекты не встречаются?
ednersky
06.11.2024 14:00ну вот допустим есть выключатель.
нажали на него (контакт замкнулся) - лампочка загорелась
повторно нажали на него (контакт снова замкнулся) - лампочка погасла
плюс есть дребезг контактов (200 мс при нажатии/отжатии)
и допустим мы программируем "умный дом" - то есть таких выключателей, подключенных к одной программе, может быть множество.
Можете набросать рыбу программы кнопка-лампочка на функциональном языке (и чтоб понятие "объект" было не нужно)?
vadimr Автор
06.11.2024 14:00В такой постановке задача неразрешима, так как мы не можем синхронизировать состояние управляющей программы с фактическим состоянием выключателя. Должна быть либо обратная связь (лучше), либо раздельные команды включения и выключения.
А когда вы введёте обратную связь, то вам не нужно будет хранить в программе состояние объекта.
Все системы управления обычно программируются полностью stateless относительно управляемых устройств, так как состояние характеризует само устройство, а не его модель в системе.
vadimr Автор
06.11.2024 14:00Так, как вы сформулировали задачу, вы никогда не знаете, горит лампочка или нет. Во-первых, вы не знаете начального состояния лампочки до запуска вашей программы. Во-вторых, у вас нет гарантии, что выключатель работает правильно (да и про ровно 200 мс на каких скрижалях написано?). В-третьих, у вас нет гарантии, что электрик Дядя Вася в какой-то момент не замкнул выключатель отвёрткой.
Поэтому у вас будет поле в объекте "состояние лампочки", с одной стороны, и фактическое состояние лампочки, с другой стороны. И они могут разойтись между собой.
Всё на самом деле ещё сложнее. Реальная история из жизни. В одном приборе было установлено механическое реле, состояние которого контролировалось программой через замыкание контрольного контакта, а всего в контактной группе замыкалось много контактов. И вот получилось так, что в процессе транспортировки реле сотряслось, и разные контакты в контактной группе оказались в разном положении. Контрольный контакт оказался замкнут, а исполнительный отошёл от замкнутого положения (или наоборот). И неудачно написанная программа заблокировалась, так как она считала реле замкнутым и не видела оснований подавать ещё одну команду на его замыкание. Так что даже с обратной связью всё не так просто, и никаких программных состояний и прочих неконтролируемых теоретических допущений о состоянии управляемых объектов быть не должно. А в этом устройстве с тех пор горячие клавиши для команд управления отрабатываются программой даже тогда, когда команды исчезают из меню на экране. Пользователю виднее. Ну, программисты зато прокатились в командировку 4 часа на самолёте.
vadimr Автор
06.11.2024 14:00Если вам интересно, то вот почти реальный код на 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) (заварить кофе)
а система уже сама разбирается, что и как для этого нужно сделать.
vadimr Автор
06.11.2024 14:00Если бы я использовал тут объектную модель, то я бы столкнулся, как минимум, со следующими проблемами.
Пришлось бы руками прописывать все возможные причинно-следственные комбинации между командами верхнего и нижнего уровня, которых, вообще говоря, экспоненциально много.
Пришлось бы каждый раз думать, какой именно класс реализует нужный мне метод, например, заварить(). Это представляет собой совершенно излишний мыслительный труд. Либо надо было бы собирать вообще все методы верхнего уровня в одном суперклассе УмныйДом, что по понятным причинам криво.
Для малейшего редактирования логики был бы нужен программист, причём перманентно озабоченный проблемой из пункта 2. Либо пришлось бы писать какой-то навороченный редактор сценариев для пользователей. Это возможный ход, и его проходили в отрасли много раз, начиная с JCL, но результаты каждый раз ужасны, так как неизменно не хватает функциональности для сложных случаев.
ednersky
06.11.2024 14:00понятие "сварить кофе" в любом случае предполагает управление кофейником.
а программирование последнего фиксирует перечень возможных операций (привязывает апи к процессу) и перечень возможных кофе машин (привязывает апи к объекту)
и вот не мытьём так катаньем у нас всё равно есть ООП
vadimr Автор
06.11.2024 14:00Понятие "сварить кофе" может также включать заказ кофе в магазине и тому подобное, что не относится к управлению одним каким-то устройством. В реальной сложной промышленной системе команда верхнего уровня вызывает последовательность управления десятками различных устройств с тысячами команд. Причём заранее очень сложно, а зачастую и невозможно, предсказать, какие команды верхнего уровня понадобятся и как конкретно они в каждом случае будут связаны с устройствами.
Поэтому в принципе, конечно, натянуть ООП на это можно (и это неоднократно делалось), но некоторые проблемы я указал в соседнем посте. Тут просто происходит некоторая подмена понятий, когда вместо семантики “сварить кофе” рассматривается семантика “включить кофе-машину”. Методом же символического продукционного вывода мы можем преобразовывать семантику совершенно корректно.
ednersky
06.11.2024 14:00в заказе тоже будут фигурировать объекты вроде магазина и банковской карточки
особенно высокоуровневые алгоритмы предполагают именно манипуляции объектами, а не числами
кстати, манипуляции строками и числами - это уже объектное программирование, просто виды объектов в данном случае предопределены
vadimr Автор
06.11.2024 14:00Вы вправе всё, что угодно, называть объектами, но реквизиты магазина и банковской карты - это структурированный текст. В Лиспе он будет, несомненно, синтаксически представлен S-выражением, которое по своей семантике, скорее всего, будет иметь тип список.
ednersky
06.11.2024 14:00реквизиты магазина - структурированный текст
а реквизиты двух магазинов? или двух банковских карточек - это уже два структурированных текста, описывающих раздельные экземпляры ОБЪЕКТОВ
и потом, в словосочетании структурированный текст, слово структурированный имеет корнем - структура.
а структура чего? того самого объекта
vadimr Автор
06.11.2024 14:00Это список, состоящий из двух списков, не равных между собой.
Не надо усложнять. А то я вас спрошу, какой смысл в двух экземплярах объекта, содержащих данные одной банковской карты.
ednersky
06.11.2024 14:00вот у вас сущности
список состоящий из двух списков
список состоящий из двух чисел
список состоящий из числа и строки
список состоящий из двух строк
просто число
просто строка
это всё объекты и есть, как от них не отворачивайся
vadimr Автор
06.11.2024 14:00В смоллтоке разве что. И то я не уверен относительно экземпляров чисел.
illinav
06.11.2024 14:00сложили числа в матрицу - появилось понятие матрицы и операторы, ей манипулирующие. и вот мы пришли к объектно-ориентированному программированию не уходя далеко от математики
С чего бы? Откуда здесь ООП и зачем?
Матрица размера n×m над полем F — это просто параметризованный F и индексированный n m тип Mat F n m, для семейства которых определены операции и константы
(+) : Mat F n m -> Mat F n m -> Mat F n m (*) : Mat f n k -> Mat F k m -> Mat F n m id : (n : Nat) -> Mat f n n
и так далее. Откуда здесь вылезают объекты?
И, кстати, как вы в чистом ООП выразите зависимость размеров матриц в операциях сложения и умножения, а также зависимость от конкретного поля?
Более того, в некоторых формализмах
Mat F n m
— это просто морфизм в категории Mat_F, чьими объектами являются натуральные числа, а множество морфизмов из числаn
в числоm
— это, как уже понятно, те самые матрицы, с очевидными операциями композиции и единицами. Но это не значит, что вам обязательно надо обмазываться теоркатом для того, чтобы перемножить две матрицы (хотя, например, известная теорема о представлении любой операции на строках через умножение на единичную матрицу, над которой проведены те же операции, является прямым и простым следствием леммы Йонеды, и через Йонеду она доказыватся в три строки, из которых две — реформулировка утверждения теоремы в категориальных терминах).
ednersky
06.11.2024 14:00в приведённом примере не scheme (это так, сноска)
Матрица размера n×m над полем F — это просто параметризованный F и индексированный n m тип Mat F n m, для семейства которых определены операции и константы
тип для которого определены операции, объект, и так далее
всё это во многих языках синонимы.
illinav
06.11.2024 14:00в приведённом примере не scheme (это так, сноска)
Вопрос синтаксиса. Мне ML-подобный синтаксис ближе. Языковой полиглот без проблем это переведёт на какой-нибудь типизированный диалект схемы, а я её только читать умею, поэтому даже не буду пытаться.
тип для которого определены операции, объект, и так далее
И поэтому каждый раз, когда у вас есть какой-то тип, для которого определены какие-то операции (кстати, скрывается ли за этим что-то большее, чем «тип является одним из аргументов или возвращаемых значений операции»?), то у вас, по-вашему, есть ООП?
ednersky
06.11.2024 14:00Ага, если пользователь может описывать новые типы и инстанцировать отдельные их значения и делает это, то он работает в ООП
Если при этом ему трудно, приходится преодолевать или изобретать велосипед, то это говорит лишь о том, что язык с ООП дружит слабо (не о том, что на языке нельзя ООП писать).
RikkiMongoose
06.11.2024 14:00emacs на C написан. LISP там - аналогично Python в Sublime или JavaScript в Atom, язык скриптов и дополнений.
vadimr Автор
06.11.2024 14:00Вроде на C написан интерпретатор Emacs Lisp, а на этом Лиспе - сам Emacs.
RikkiMongoose
06.11.2024 14:00Там архитектура более сложная: https://chrismennie.ca/EMACS-Conceptual-Architecture.pdf
Но в том же vim макросы уже процедурные, а не LISP-поподобные.
ednersky
06.11.2024 14:00не знал (правда).
мне всегда казалось что это именно с ног до головы LISP приложение
vadimr Автор
06.11.2024 14:00Если б его писали сейчас, был бы целиком на лиспе, к гадалке не ходи. Но в те времена Лисп очень тормозил.
RikkiMongoose
06.11.2024 14:00ZED (из недавно вышедших) написан на Rust.
Что в нём нового по сравнению с Sublime - не очень ясно.
AuToMaton
06.11.2024 14:00За Scheme можно было ещё словечко замолвить. Racket есть в Termux пакетом, а вот пакета Julia в Termux нет. И на Андроид есть диалект Lisp как относительно рабочее приложение, а на iPad есть прямо таки Scheme, хотя и называется LispPad. И Scheme развивается достаточно медленно и поэтому везде более-менее одинаковый, чем выгодно отличается от того же Python который почти везде не актуальный.
Книжка SICP в 2022-м году вышла перепетая на JavaScript.
justaoneuser
06.11.2024 14:00Эпический тред там выше про ООП, ФП, типы, кто из них круче и всякое такое. Обычно не участвую в таких дискуссиях, но тут не удержаться. Печально, что люди так критически относятся к новой для них информации.
Вот промисы в том же JS: есть две ветки выполнения - resolve и reject - и состояние, упакованное в контейнер. Пусть @illinav поправит, но очень похоже на монаду.
Только в чистых функциональных языках, это всё ещё и строго типизировано. Хотя даже с ограниченной типизацией у такой структуры данных есть ощутимые преимущества, что мы и видим на примере JS. Промисы не обязательно использовать только для асинхронщины, такой контракт вообще повышает безопасность и читаемость кода.
@RikkiMongoose.Кстати, вот насчёт типизации и гарантий в "compile time" (в широком смысле), никто же не будет спорить что "use strict" штука полезная.
ESLint, TypeScript - тоже классные инструменты. Насколько понимаю, Haskell и, тем более, Idris, например, - это как TypeScript на максималках.
@ednersky Спор выше по сути не про ООП, а про слабые и сильные системы типов. И вот как то так получилось, что у большинства ООП-языков система типов слабая (по сравнению с). И приходится выкручиваться паттернами и линтерами и тестами там, где могли бы эффективнее работать типы.
В общем даже со слабой системой типов многие функциональные техники полезны и в JS, композиция функций, замыкания, частичное применение, многое другое. А с сильной системой типов - всё это ещё и безопаснее и легче читается (просто по аннотациям).Что популярно и где используется - вообще странный аргумент, вот Blackbird - чудо своего времени, но использовался крайне ограниченно, так и тут.
Возможно, что то из функциональных (в том числе "экзотических") языков ещё перейдёт в тот же JS / TS (и другие мейнстримные языки). Такое уже не раз было...vadimr Автор
06.11.2024 14:00Вообще система типов и ФП - это довольно независимые вещи. Хотя своего наивысшего развития, безусловно, система типов достигает в типизированных ФП языках. Но Лисп и его диалекты основаны на бестиповом лямбда-исчислении, и это имеет свои практические преимущества, особенно в системном программировании, так как архитектура фон Неймана бестипова.
Что касается промисов (которые вроде как раз из Scheme изначально и пошли), то они, скорее, представляют собой организацию ленивого вычисления руками. Но пользы от этого, честно сказать, гораздо меньше, чем от настоящего ленивого порядка вычислений, как в Хаскеле. Хотя иногда бывает полезно.
nick0x01
SICP может быть несколько сложным для начала. Можно начать с "How to Design Programs, second edition: An Introduction to Programming and Computing", в русском переводе: "Как проектировать программы. Введение в программирование и компьютерные вычисления".
RikkiMongoose
Эта книга может вам пригодиться только если вы станете попаданием в год эдак 1986. Тогда описанные там знания станут для вас очень актуальны.