Лисп в изгнании
229 subscribers
156 photos
21 videos
5 files
233 links
Авторский канал на околоайтишную тематику.

По всем вопросам @awkravchuk
Download Telegram
Сегодня в нашем клубе прошло интересное мероприятие с Warhammer Montenegro. Всем, кто пришел и поддерживает направление настольных игр, огромное спасибо. Будем рады вас видеть на дальнейших встречах =)
🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
#лытдыбр #common_lisp #видео

На своём утреннем стриме, потихоньку проникаясь Test-Driven Development (моего внутреннего перфекциониста-аутиста очень радует превращать свеженаписанные проваливающиеся тесты в вереницу зелёненьких), наткнулся на уморное сообщение от компилятора SBCL, см. видос. ЛЕКСИЧЕСКОЕ ОКРУЖЕНИЕ СЛИШКОМ ВОЛОСАТОЕ, КАРЛ!
1
#лытдыбр

Спам категории «фэнтези»: г-н Кадзухиро Токимаса из ЯНДЕКСа пишет с домена outlook.com и предлагает присоединиться к его команде за щедрое вознаграждение в размере 2000 рублей в день. В принципе, уровень зарплаты как раз яндексовский, но в остальном, конечно, эклектика
1🔥1
#лытдыбр #common_lisp

Джоба успешно закончилась, а таймер всё тикает. Я смотрю, Gitlab меня решил на счётчик поставить 😂
😁1
#лытдыбр #common_lisp #проекты

На протяжении уже пары недель маниакально работал, чтобы вчера выпустить версию 0.1.1 своего мини-фреймворка для паттерна Entity-Component-System на Common Lisp: https://gitlab.com/lockie/cl-fast-ecs
Пока там только базовая функциональность, но я продолжаю маньячить над кодом на утренних стримах 😅
4
#лытдыбр

Дожили, использую ЧятЖПТ, чтобы придумывать имена переменным 😅 Как известно, именование — одна из двух самых сложных проблем в программировании, наряду с инвалидацией кэшей и off-by-one-error, так что не грех для этого использовать математическую модель с миллиардами параметров)
Довольно интересный экспириенс, оно не даёт каких-то внятных, готовых к использованию ответов, но по мере того, как пытаешься сформулировать правильный промпт, сам начинаешь понимать, что же тебе нужно, и вот уже оно становится не нужно 😁
👍1
#common_lisp

И вот через пару недель работы над Common Lisp'овым фреймворком для паттерна Entity-Component-System есть, чем повыёбываться 😊
Предельно ясный и высокоуровневый код вида

;; определяем компонент "позиция" с вещественными полями x и y
(defcomponent position
(x 0.0 :type single-float)
(y 0.0 :type single-float))

;; определяем аналогичный компонент "скорость"
(defcomponent velocity
(x 0.0 :type single-float)
(y 0.0 :type single-float))

;; определяем систему "движение", которая вычисляет позицию всех сущностей
;; с позицией и скоростью в соответствии с нехитрыми физико-математическими соображениями
(defsystem move
(:components-ro (velocity)
:components-rw (position))
(incf position-x velocity-x)
(incf position-y velocity-y))

после всех нужных притоптываний и приплясываний транслируется замечательным лисповым компилятором SBCL в следующий машинный код (комментарии мои):

disassembly for MOVE-SYSTEMG186
Size: 315 bytes. Origin: #x535A956E
MOV RAX, [R9+45]
TEST BYTE PTR [RAX+1], 1
JEQ L6 ; по метке L6 мы проверяем ещё один бит в [RAX+1]:
L0: MOV [RBP-8], R8 ; если с предыдущего запуска системы к каким-либо сущностям
MOV [RBP-16], R9 ; не добавлялись и не удалялись компонеты, мы обойдём этот
MOV RDI, [R8-7] ; кусок кода и окажемся в метке L1
SUB RSP, 16 ; если же что-то поменялось, будет перестроен и записан на будущее
MOV RDX, R9 ; битовый индекс тех сущностей, которые система должна обходить
MOV RSI, [RIP-302]
MOV ECX, 6
MOV [RSP], RBP
MOV RBP, RSP ; собственно, вот этой функцией и будет перестроен
MOV EAX, #x502EE502 ; #<FDEFN CL-FAST-ECS::%REBUILD-ENTITIES-BITMAP>
CALL RAX
CMOVB RSP, RBX
MOV R9, [RBP-16]
MOV R8, [RBP-8]
MOV RAX, R8
SHR RAX, 10
AND EAX, 1048575
MOV BYTE PTR [R12+RAX], 0
MOV [R8-7], RDX
L1: MOV RSI, [R9+37] ; итак, метка L1: записываем пару вещей в регистры и прыгаем на L4
MOV RDI, [R9+13]
XOR EBX, EBX
JMP L4
NOP
NOP
L2: MOV RCX, [R8-7]
MOV RDX, RBX
SAR RDX, 1
MOV RAX, RDX
SHR RAX, 6
MOV RAX, [RCX+RAX*8+1]
BT RAX, RDX
JB L5
L3: ADD RBX, 2
L4: CMP RBX, RDI ; а на L4 как раз начинается главный цикл системы, который будет
JL L2 ; проходить по всем нужным ей сущностям.
LEA RBX, [RBP+16] ; прыгаем на L2, где делаем два хопа по памяти, чтобы слазить в битовый индекс,
XOR ECX, ECX ; и если понимаем, что нам нужна очередная по номеру сущность, прыгаем на L5
MOV EDX, #x50000117
MOV RDI, RDX
MOV RSI, RDX
STC
MOV RSP, RBP ; если цикл закончился, чистим стек и возвращаемся из функции
POP RBP
RET
L5: MOV RAX, [RSI+1] ; на L5, собственно, и происходят наши сложнейшие вычисления с прибавлением
MOV RCX, [RSI+9] ; к position-x значения velocity-x и то же для y
MOV RDX, [RCX+21] ; подчеркну, что доступ к каждому полю компонента обходится в ещё два хопа по памяти,
MOVSS XMM1, [RDX+RBX*2+1] ; и они последовательные, поэтому аккуратно оседают в кэшах CPU
MOV RCX, [RCX+29]
MOVSS XMM3, [RCX+RBX*2+1]
MOV RCX, [RAX+21]
MOVSS XMM2, [RCX+RBX*2+1]
ADDSS XMM2, XMM1
MOV RCX, [RAX+21]
MOVSS [RCX+RBX*2+1], XMM2
MOV RCX, [RAX+29]
MOVSS XMM1, [RCX+RBX*2+1]
ADDSS XMM1, XMM3
MOV RAX, [RAX+29]
MOVSS [RAX+RBX*2+1], XMM1
JMP L3 ; закончив весь матан, уходим на следующую итерацию цикла по сущностям на L3
L6: TEST BYTE PTR [RAX+1], 2
JEQ L1
JMP L0

Ну камон, 315 байт машинного кода почти без всякого лишнего дроча — это достижение, до которого всяким там обоссанным Unity3D срать и срать 😁
👍4🔥4
#лытдыбр

Вчера на моём курсе по C один из студентов защитил проектную работу, в которой под моим чутким руководством сделал header-only библиотеку для создания замыканий на сишечке, с ручным созданием функции-трамплина в рантайме и с полуавтоматическим управлением памятью. Библиотека, конечно, чистой воды proof-of-concept и не для использования в продакшене, но всё равно требовала для своей реализации кропотливой работы, так что вы знаете, куда насыпать звёздочек
К слову, на днях тут вписался на бесплатный мини-курс по созданию своего интерпретатора лиспа, там подобного рода трюки с замыканиями вполне себе пригодятся. Курс начинается сегодня, так что вы ещё можете успеть тоже вписаться) Для этого нужно написать в личку @IIvana
👍4
#мемасики #common_lisp

По мотивам сегодняшнего стрима 😅
Писать макросы, которые определяют макросы, это каждый раз адский заворот мозговых извилин 🤯
#common_lisp

Меж тем, тихо и незаметно вышла новая версия моего ECS-микрофреймворка для Common Lisp с исправлениями производительности и инкрементальными улучшениями API.

В ближайших планах — чуть больше сместиться в сторону маркетинга и написать про него пару популяризующих статей ☺️
👍6
#репост

Как говорится, вашими бы устами да мёд пить.
Давно уже понял про себя, что мне куда больше по душе проекты-долгострои, нежели проекты с чётко очерченными дедлайнами, хотя дедлайны, конечно, по-своему тонизируют. Примерно как рука, спросонья обожжённая об горячую плиту тонизируют, ага.
2👍1
#лытдыбр #common_lisp

Взявшись за написание красивой демки для своей ECS-библиотеки, вот уже во второй раз натыкаюсь на какой-то совершенно адский фундаментальный косяк, который каким-то образом не был выловлен автоматическими тестами. Видимо, придётся сегодня сделать ещё один минорный релиз, а то вдруг Зак наконец разродится новым апдейтом Quicklisp и в нём окажется версия моей библиотеки с багом. Нет слов, как же я на себя зол 😡
🔥2
#репост #common_lisp

Во многом согласен с коллегой по лисповому сообществу, просто не могу не репостнуть 😊
Forwarded from akater
Я выбрал Лисп по нескольким причинам, но в ретроспективе получается, что многие из них вытекают из «Лисп дает своему пользователю максимальную свободу». (Лиспом я называю язык, где есть defun, defmacro, defmethod, unwind-protect, loop, и все это охотно используется.)

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

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

Мне было и есть неприятно программировать не на Лиспе. И по сей день, когда мне нужно написать какое-то сложное условие для if в shell script, я нередко ищу в вебе, какие буквы там писать — и иногда так и не нахожу! Это безумие. В Лиспе с его универсальным (f x y) мне этого никогда не нужно делать, и это было первое, что мне в свое время понравилось в первом языке, на котором мне было приятно программировать (Wolfram Language / Mathematica).

Лисп обеспечивает «первую свободу» по Столлману больше, чем что-либо еще, т.к. он дает максимум возможностей и удобства модифицировать работающую программу. Никто не пользуется первой свободой так, как пользователи GNU Emacs, и это благодаря Лиспу. И я уверен, что никакая социальная группа юзеров опенсорс в мире не читает исходники так активно, как это делают пользователи Emacs.

Первую свободу дает интерактивность. Можно перекомпилировать отдельную функцию в любой момент, и она становится частью работающей сейчас системы. В Common Lisp нет неизбежной необходимости дублировать выполненные вычисления из-за возникшей в ходе вычисления ошибки, благодаря кондишнам. Состояние программы всегда можно поправить, находясь в самой программе. Я никогда не думаю, что «я пишу код» — я живу в системе, которую расширяю. Это все характеризует интерактивность, недоступную за пределами Лиспа. Помимо интерактивности, в первую свободу делает важный вклад свобода самовыражения.

Не так давно я общался с одним студентом, который активно пишет на Python. Мы обсуждали какой-то его код на Python, и я спросил «почему бы тут не написать switch»? И он сказал «в Python, к сожалению, нет switch». Мне это вновь напомнило, насколько ужасна была бы для меня жизнь как у тех, кто не может себе написать switch, или, скажем, добавить в функции киворды / kwargs по-пайтоновски, если этого нет.

Лисп — это для меня не язык. Это система программирования и способ взаимодействовать с компьютером, разумная альтернатива Юниксу. Я собираюсь так взаимодействовать с компьютером, пока не умру. Сейчас я живу в GNU Emacs, разумеется. Именно Лисп делает это возможным, и альтернатив попросту нет.
🔥6
#common_lisp #лытдыбр

Итак, дёмка моего ECS-фреймворка работает примерно в 5-6 раз медленнее, чем аналогичный код с использованием C-шного фреймворка Flecs. Чего-то подобного я ожидал, но всё равно неприятно. Поверхностный анализ показал, что прорва времени теряется на уровне FFI, при вызове функций для отрисовки из liballegro. Полез разбираться — выяснилось, что в liballegro структура с указанием цвета ALLEGRO_COLOR передаётся во все функции "по значению", т.е. не через указатель, а тупо все поля складываются на стек; а документация к лисповому компилятору SBCL гласит, что "Passing of structures by value is not implemented", поэтому CFFI для передачи этой структуры городит в результирующем коде какой-то адский фарш из дженериков и ручного выделения памяти на куче под эту структуру, я вообще удивлён, что это в 5 раз медленнее, а не во все 50.
Решил для дёмки попробовать какую-нибудь другую графическую либу вместо liballegro, и тут выяснилось, что практически все из них (ну окей, не все, а raylib и SFML), как будто сговорившись, передают структуры с цветом по значению, и только набившая оскомину SDL2 с довольно среднего качества лисповыми биндингами принимает компоненты цвета по-человечески, тупо целочисленными аргументами на стеке, наглядная демонстрация: на SDL выставление цвета отрисовки занимает 153 байта машинных инструкций, вместе с проверкой на ошибки, а на liballegro одно только создание структуры с цветом занимает почти два килобайта (!).
Буду завтра на стриме переписывать дёмку на SDL2, чо 😅
5🤪1