Forth – Is it still relevant?
Представлена реализация eForth на C/C++ с кроссплатформенной поддержкой. Проект работает на Linux, MacOS, Windows, ESP32 и даже в WebAssembly (WASM), что делает его универсальным решением для различных систем.
Код проекта размещен на GitHub в репозитории chochain/eforth. Реализация eForth на C/C++ позволяет использовать этот язык программирования в широком спектре устройств - от настольных компьютеров до встраиваемых систем вроде ESP32, а также в веб-среде через WASM.
Комментарии (47)
- Forth ценен для образования как альтернативный подход к вычислениям наряду с Lisp, демонстрирующий разные способы выражения программной логики.
- Классические реализации Forth на ассемблере противоречат идее 100% C/C++ с кросс-платформенностью, но язык остается простым для реализации с нуля, особенно на стековых процессорах.
- Производительность Forth часто страдает из-за цепочек вызовов подпрограмм, но возможна оптимизация через инлайнинг, использование регистров и native-код для критичных участков.
- Forth сохраняет нишевое применение в embedded-системах благодаря компактности и гибкости от низкоуровневого до высокоуровневого программирования.
- Сообщества вокруг таких языков могут предлагу уникальные решения, но иногда склонны к догматизму и пренебрежению другими подходами.
An Algebraic Language for the Manipulation of Symbolic Expressions (1958) [pdf]
Эта работа представляет спецификацию алгебраического языка для манипуляции символьными выражениями, разработанного Джоном Маккарти. Язык предназначен для программирования формальных математических процессов (алгебраическое упрощение, дифференцирование, интегрирование), написания компиляторов (кроме ввода/вывода) и эвристических программ, где удобно представлять деревья альтернативных действий. Он особенно эффективен для работы с выражениями переменной длины и структуры, имеющими подобподвыражения, но менее удобен для списков фиксированной длины.
Выражения в языке представляются списками, где каждый элемент занимает машинное слово, содержащее данные и адрес следующего элемента. Маккарти отмечает, что удобство алгебраической нотации связано с возможностью композиции функций без именования промежуточных результатов и построения сложных структур путем вложения вызовов функций, формирующих списки. Ключевыми особенностями языка являются поддержка рекурсии с автоматическим сохранением промежуточных результатов в структурах списков и мощные условные выражения, решающие проблему выбора операций на основе результатов тестов. Маккарти ссылается на ранние работы Ньюэлла, Саймона и Шоу по эвристическому программированию и Гелентера в геометрической программе как предшественников.
Комментарии (11)
- Появление первых отчетов о LISP в 1958 году стало поворотным моментом, поскольку они ввели ключевые концепции, которые позже стали основой для многих языков программирования.
- Исторически важно, что McCarthy и его команда в MIT в 1958 году разработали и документировали эти ранние отчеты, включая в них идеи, которые до сих пор используются в современных языках.
- Отчеты показали, как LISP влиял на развитие компьютерных наук, включая идеи о списковой обработке, рекурсии, и функциональном программировании.
- Несмотря на то, что эти отчеты были написаны более 60 лет назад, они до сих пор влияют на разработку языков программирования и остаются актуальными для изучения истории ИИ и вычислительных наук.
- Некоторые участники обсуждения подчеркнули, что эти отчеты не только исторически важны, но и могут быть использованы для образовательных целей, чтобы изучать основы компьютерных наук и эволюцию языков программирования.
Lisp: Notes on its Past and Future (1980)
LISP просуществовал 21 год к 1980 году, потому что представляет собой приблизительный локальный оптимум в пространстве языков программирования. Маккарти отмечает, что язык накопил некоторые "балластные" элементы, которые следует устранить, и упустил возможности для улучшений. Языку помогло бы совместное обслуживание, особенно в создании и поддержке библиотек программ. Компьютерно проверяемые доказательства корректности программ теперь возможны для чистого LISP и некоторых расширений, но для полного использования математической основы языка требуется больше теории и упрощения самого языка.
В примечании 1999 года Маккарти отмечает, что его взгляды 1980 года в основном соответствуют текущим. Основная идея заключается в том, что LISP, несмотря на свою долговечность, нуждается в очистке от лишних элементов и улучшении для раскрытия его полного потенциала, особенно в области формальных доказательств корректности программ.
Комментарии (95)
- Обсуждение показало, что Lisp и его диалекты всё ещё живы, но в нишевых формах: от Clojure на JVM до CHICKEN Scheme, компилирующего в C.
- Участники отмечают, что язык остаётся мощным инструментом, но его экосистема и сообщество сильно сократились, и нет признаков возвращения в мейнстрим.
- Некоторые подчеркнули, что Lisp-языки всё ещё важны для AI-исследований, генетического программирования и метапрограммирования.
- Сообщество отметило, что популярность языка упала не из-за технических причин, а из-за смены парадигмы в разработке ПО от символического AI к нейронным сетям и статистическому программированию.
Abstraction, not syntax
В статье обсуждается, что главная проблема конфигурационных файлов — не синтаксис, а отсутствие абстракций. Хотя многие ругают YAML за сложность, реальная проблема в том, что даже простые форматы вроде JSON не решают проблему дублирования и ошибок вроде опечаток в числовых константах.
Автор показывает на примере: если нужно описать несколько однотипных ресурсов (в примере — cloud-бакетов для бэкапов), то даже в JSON или YAML придётся дублировать код, что ведёт к ошибкам. Например, в одном месте указали 2592000 секунд (30 дней), а в другом — 259200 (пропустили ноль), и из-за этого данные удаляются через 3 дня, а не 30.
Решение — использовать язык конфигурации, который поддерживает абстракции, как в языках программирования. Например, RCL позволяет использовать переменные, циклы и вычисления, что исключает ошибки из-за опечаток и дублирования. Так, вместо шести повторяющихся блоков конфигурации можно написать один цикл, который сгенерирует их все, гарантируя, что все значения согласованы.
Хотя некоторые форматы (как HCL) тоже поддерживают выражения, важно, чтобы их хватало для полного устранения дублирования. Поэтому при выборе формата конфигурации стоит смотреть не только на синтаксис, но и на возможность абстракций.
Комментарии (51)
- Обсуждение в основном вращается вокруг того, что конфигурационные языки (YAML, JSON, TOML и т.д.) не масштабируются и не имеют абстракций, что приводит к необходимости встраивать в них полноценные языки программирования, что в свою очередь создает проблемы безопасности и предсказуемости.
- Участники обсуждения подчеркивают, что вместо того, чтобы изобретать новые конфигурационные языки, следует использовать существующие общеязыковые инструменты (Python, Lisp и т.д.) для конфигурации как код, что позволит избежать проблем с безопасностью и сложностью.
- Некоторые участники также упоминают, что проблема не в синтаксисе или структуре данных, а в отсутствии стандартного языкового сервера для конфигурационных файлов, что делает невозможным автодополнение и переход к определению.
- Также поднимается вопрос о том, что если конфигурационный язык предоставляет возможность встраивать код, то это может быть использовано для вредоносных целей, и вопрос о том, как обеспечить безопасность таких файлов, становится критически важным.
- В конце концов, обсуждение сходится на том, что вместо того, чтобы продолжать изобретать новые конфигурационные языки, следует использовать существующие языки программирования и инструменты, которые уже решают эти проблемы.
Show HN: Kent Dybvig's Scheme Machine in 400 Lines of C (Heap-Memory Model)
Виртуальная машина для языка Scheme реализована на C с использованием кучи для хранения пар. Основана на модели из работы Дабвига «Three Implementation Models for Scheme», что делает её компактным учебным примером интерпретатора Lisp-подобных языков.
Лексический анализатор разбивает входную строку на токены, а парсер строит из них списковые структуры через функцию cons. Пары хранятся в статическом массиве text, что упрощает управление памятью. Поддерживаются базовые конструкции: атомы, списки, цитирование через апостров. Вывод структур реализован рекурсивно с учётом точечной нотации.
Комментарии (40)
- Обсуждение производительности и особенностей различных реализаций Scheme, включая Chez Scheme, MIT Scheme и другие.
- Упоминание роли Кента Дибвига как создателя Chez Scheme и его влияния как преподавателя и исследователя.
- Вопросы о технических деталях и возможных ошибках в представленном коде, включая проблемы с указателями и порядком вычислений.
- Идеи о бутстраппинге компиляторов и интерпретаторов, включая использование LLM для генерации ассемблерного кода.
- Общие положительные отзывы о минималистичных и элегантных реализациях Scheme, таких как обсуждаемый код.
Delimited Continuations in Lone Lisp
Lone Lisp теперь поддерживает ограниченные продолжения — мощный механизм управления потоком выполнения. Это позволяет сохранять и восстанавливать состояние вычислений в определённых точках, что открывает путь к реализации генераторов, обработки исключений и других сложных конструкций. Пример кода демонстрирует, как control и transfer работают вместе: (control ...) захватывает контекст, а (transfer ...) передаёт управление, позволяя гибко манипулировать выполнением.
Изначально проблема возникла при реализации итераций: из-за рекурсивной природы интерпретатора и управления стеком на уровне C было невозможно контролировать поток. Решение потребовало переосмысления архитектуры — вместо байткода или трансформаций в стиле продолжений автор выбрал подход, сохраняющий списковую структуру Lisp. Это сложный, но фундаментальный шаг, вдохновлённый классическими работами вроде SICP.
Комментарии (8)
- Wat реализует стек вызовов в пользовательском пространстве для поддержки ограниченных продолжений, что позволяет создавать исключения, ветвление и файберы.
- Вопрос о практическом применении ограниченных продолжений за пределами хобби-проектов и их реальном использовании в промышленности.
- Примеры использования в Ocaml 5 (библиотека Eio), Haskell (GHC, работа приостановлена) и Racket (стандартная модель для обработки ошибок и прерываний).
- Java использует ограниченные продолжения как основу для своих новых "зеленых" потоков (виртуальных потоков).
- Обсуждение потенциальных сфер применения, таких как встраиваемые системы.
Комментарии (31)
- Обсуждаются исторические Lisp-процессоры (SCHEME-78, Symbolics 'Ivory', TI) и причины их коммерческого неуспеха: высокая стоимость, проприетарность и несоответствие массовому рынку.
- Выдвигается тезис, что даже если бы такие процессоры выбрали для IBM PC, они бы проиграли из-за архитектурных недостатков и быстрого прогресса традиционных CPU и компиляторов.
- Отмечается связь между разработчиками SCHEME-78 (Гай Стил, Дэнни Хиллис) и их работой в MIT, а также последующим созданием Connection Machine.
- Упоминается важность работ Линн Конвей по VLSI-дизайну и курса, на котором студенты впервые проектировали и производили чипы.
- Обсуждается превосходство специализированных сред, подобных Interlisp-D, над современными инструментами разработки.
Introduction to Nyquist and Lisp Programming
Nyquist и Lisp в Audacity
Nyquist — язык для синтеза и анализа аудио, написанный Р. Данненбергом. Audacity использует его подмножество; плагины создаются обычным текстом, без компиляции. Поддерживаются Lisp и C-подобный SAL (до 1.3.8 — только Lisp).
Lisp за 2 минуты
Всё — S-выражение: (функция аргументы…)
Пример: (setf area (* 3.14159 (expt radius 2)))
-
Математика: префиксная нотация
(* 3 7) -
Своя функция:
(defun circlearea (r) (* 3.14159 (expt r 2)))
(setf a (circlearea 5)) -
Списки:
(setf lst '(1 2 3))или(list 1 2 (sqrt 9))
first/rest— доступ к элементам.
Ключевые функции
+ - * / abs sqrt min max expt sin cos tan
listp length reverse sort (first/rest)
if when unless cond
Готово — можно писать эффекты прямо в Audacity.
Комментарии (1)
- Участники удивлены, что кто-то всё ещё поддерживает SAL.
- Большинство давно перешли на обычный Lisp; SAL встречается лишь в старых проектах.
- Новые пользователи даже не знают о существовании SAL.
Lisp interpreter with GC in <750 lines of Odin (and <500 lines of C)
Проект LISP
Репозиторий krig/LISP заархивирован 28 авг 2025 г. и доступен только для чтения.
Разработка перенесена на Forgejo.
Комментарии (32)
- Участники обсудили, что минималистичность Lisp объясняется простотой синтаксиса (s-выражения) и всего трёх базовых форм: quote, cond, lambda.
- @krig показал свой 750-строчный интерпретатор на Odin, подчеркнув, что это учебный проект, а не продакшн-решение.
- Появились вопросы по синтаксису Odin (различие := и =), а также замечания о скорости и полезности такого «игрушечного» кода.
- Упомянули полезные ссылки: оригинальную статью Маккарти, объяснение Грэма, описание semi-space GC от Andy Wingo.
- Некоторые участники поделились личными впечатлениями о создателе Odin и культуре обсуждений вокруг языка.
Lisp from Nothing, Second Edition 🔥 Горячее
LISP FROM NOTHING
344 стр., 2025, Lulu Press, 6"×9", 19 иллюстраций, код бесплатно.
Купить: мягкий переплёт | твёрдый | PDF
Исходники | Превью (PDF) | Опечатки | Видео-обзор
Книга исследует минимальный LISP, способный интерпретировать и компилировать себя, и показывает, каким был хакинг в эпоху перфокарт и мейнфреймов. Во втором издании добавлена глава о связи LISP с λ-исчислением, улучшены макросы и стиль.
Примеры кода
- Метациркулярный интерпретатор: CL, Scheme
- Компилятор (~400 строк): liscmp.lisp.html
- Система: lisp.lisp.html
- Сборщик мусора: gc.lisp.html
Весь код книги (~100 КБ)
λ-исчисление в Scheme (~6 КБ)
Генератор перфокарт Postscript
Обложка главы «Let There Be LISP»
Комментарии (97)
- Читатели восторженно отзываются о сайте и книгах Нильса М. Хольма, называя их «личной поэзией» и «культурными артефактами», созданными ради самого процесса.
- Автор подтверждает: главное для него — красота и простота изложения, а не практическая польза или научная новизна.
- Покупатели жалуются на выбор: «хочется всё сразу», но автор советует начать с одной книги и прислал шпаргалку «какую выбрать».
- Обсуждаются входные требования: книга не для новичков; рекомендуют The Little Schemer, ANSI Common Lisp и A Gentle Introduction.
- Возник спор о названии «Lisp from Nothing» при пометке «не вводная книга»; автор уточняет, что «nothing» значит «с нуля», а не «для нулевых».
Do I not like Ruby anymore? (2024)
Перешёл в компанию, где стек — Python. Выбор был не из-за языка: Python мне всегда казался гигантским красным флагом. Тем не менее, начинаю к нему привыкать.
Почему я любил Ruby
Ruby — мой первый «язык-любовь»: всё объект, if можно переписать блоками, method_missing позволяет метапрограммировать. Он черпал у Smalltalk и Lisp, и это вдохновляло.
Почему ненавидел Python
Python казался «хуже Ruby» и «ещё хуже Scheme». if — оператор, а не выражение; lambda уродливые; до Python 3 print вообще был оператором. Один «правильный» способ делать всё раздражал.
Типы для нетипизированного
Потом пришёл TypeScript: мощная система типов, narrowing, conditional types. Плохие конструкции языка прощаются статическим анализом.
Я изменился
TypeScript научил: отсутствие match или if-выражения пережить, если компилятор проверит инициализацию. Rust показал, что мутабельность — не зло.
Python изменился
Теперь в Python есть type hints, match с деструктуризацией, а print — функция.
Комментарии (127)
- Автор рассказал, как после появления VSCode и LSP перестал использовать языки без типов и теперь не хочет возвращаться к Ruby без нормальной типизации.
- Участники обсуждают, что Ruby остаётся элегантным и «радостным», но его отказ от постепенной типизации (включая Sorbet) отталкивает многих.
- Python, напротив, эволюционирует: появились аннотации типов, LSP, но язык стал сложнее и уже не «выучить за выходные».
- Некоторые считают, что страсть к Ruby — это ностальгия, а промышленность требует стабильности и инструментов, которые дают статические языки.
- Общий вывод: выбор языка всё чаще диктуется экосистемой, инструментами и личными приоритетами, а не чистой «красотой» синтаксиса.
The Unix-Haters Handbook (1994) [pdf]
PDF-1.2, 8191 объект, линеаризован, 598 xref-записей.
Содержит структуру документа (каталог, страницы, шрифты, потоки), но без текста.
Все данные — служебные, читаемого контента нет.
Комментарии (106)
- Книга «The Unix-Haters Handbook» вызывает смешанные чувства: кто-то видит в ней ценный исторический артефакт и живую критику, кто-то — просто троллинг.
- Участники вспоминают конкретные «болячки» Unix: sendmail, csh, права доступа, «всё есть файл», который не всегда работает.
- Многие признают, что за 30 лет часть проблем решена, но новые появились — например, systemd, который теперь вызывает аналогичную ненависть.
- Любовь к Unix всё же сохраняется: дёшевые процессы, пайпы и «всё есть текст» делают систему удобной, особенно с помощью современных ИИ-ассистентов.
- В дискуссии всплыли ностальгия по Lisp-машинам, шутки про EMACS, барф-баг в комплекте книги и даже возможный «systemd haters handbook».
Dynamically patch a Python function's source code at runtime
Как заменить код функции «на лету»
Python позволяет переписывать тело функции во время работы программы:
-
Берём исходник новой функции как строку.
new_src = "def f(x): return x * 2" -
Компилируем:
code = compile(new_src, "<magic>", "exec") -
Выполняем в нужном пространстве имён:
ns = {} exec(code, {}, ns) -
Подменяем старую функцию:
f = ns["f"]
f(21) теперь возвращает 42.
Зачем это нужно
Такой трюк позволяет LLM-агентам генерировать и сразу запускать код с доступом к текущему контексту. Это удобно для ToolBot, но открывает огромную дыру в безопасности: любой сгенерированный код получает доступ ко всем переменным процесса.
Комментарии (69)
- @breuleux показал jurigged — библиотеку для горячей перезагрузки только изменённых функций без перезапуска модулей.
- Участники сравнили приём с monkey-patching, Lisp-овой «код как данные» и REPL, отметив плюсы и отладочные грабли (стек-трейсы вида
<magic>). - Обсуждали, где ещё работает такое: JVM/CLR, Erlang, динамические библиотеки в C/C++ и игровые движки.
- Кто-то считает это мощным, кто-то — анти-паттерном; всплыли ссылки на autoreload, forge и swanky-python.
- Наконец, всех достала навязчивая привязка любой темы к AI-хайпу.
A Lisp in 99LOC
tinylisp — лисп-интерпретатор всего на 99 строк C.
Включает 21 примитив, сборщик мусора и REPL.
Доступны варианты с оптимизацией хвостовой рекурсии для ускорения и экономии памяти.
Комментарии (16)
- Участники обсуждают крошечную реализацию Lisp, которую, по словам одного комментатора, могли писать для карманного компьютера Casio AI-1000 1989 г.
- Код раскритикован за «ужасный» стиль на C: злоупотребление double, нарушения strict aliasing и эндиан-зависимость.
- Предложены альтернативы: 100-строчный Lisp на Python, tinylisp, lispy.py Питера Норвига.
- Найдена синтаксическая ошибка в tinylisp (лишняя скобка) и отмечено отсутствие TCO, из-за чего Y-комбинатор не работает без доработки.
Compiling a Lisp: Lambda lifting
Переписал Ghuloum-туториал на Python (~300 строк). Убрал читалку S-выражений и бинарный код — теперь текстовая ассемблерная печать.
Lambda-lifting требует:
- знать связанные переменные;
- собирать свободные переменные лямбд;
- накапливать создаваемые
code-объекты.
Связывают let и lambda; для них обновляем окружение.
Lifter
class LambdaConverter:
def __init__(self):
self.labels = {}
def convert(self, expr, bound, free):
match expr:
case int() | Char() | bool():
return expr
case str() if expr in bound or expr in BUILTINS:
return expr
case str():
free.add(expr)
return expr
case ["if", t, c, a]:
return ["if",
self.convert(t, bound, free),
self.convert(c, bound, free),
self.convert(a, bound, free)]
lift_lambdas запускает обход и возвращает (labels …).
Lambda
Лямбда:
- связывает параметры;
- выделяет код;
- захватывает внешнее окружение.
Пример:
(lambda () x) ; x свободна
превращается в
(labels ((f0 (code () (x) x)))
(closure f0 x))
Даже если x связан снаружи, внутри лямбды он считается свободным.
Комментарии (15)
- Участники рекомендуют три современные книги по компиляторам, вдохновлённые статьёй Ghuloum: «Writing a C Compiler» (Sandler), «Essentials of Compilation» на Racket и Python (Siek).
- Обсуждали «lambda lifting»: преобразование, выносящее замыкания наверх, уменьшая их размер вплоть до полного исчезновения.
- Уточнили, что «lambda lifting» в статье связан с разделом 3.11 о сложных константах в Scheme.
- Разбирали, почему современный ИИ использует Python, а не Lisp: удобство как «клея» для C++/CUDA, упадок доли рынка Lisp и смена парадигмы ИИ.
Build Your Own Lisp 🔥 Горячее
—
Комментарии (72)
I learned recently that the creator of the Iosevka typeface did so using their own Lisp implementation.The typeface:https://github.com/be5invis/IosevkaThe language:https://github.com/be5invis/PatELTheir tool which they used to build the language:https://github.com/be5invis/patris