Pull to refresh

Comments 21

Хм... Я к сожалению только начинающий в web разработке, но успел немного почитать первые статьи Пол Грэма, которые очень много говорят о Lisp, но в довольно старые времена, также Пол Грэм рассказывает о проблемах и перспективах Lisp и Web вцелом, затрагивает проблемы популярности новых ЯП и их использовании в разработке web-приложений. К сожалению проблему, которую обозначил Пол Грэм еще в далекие времена до сих пор актуальна – Web- приложения разрабатываются и поддерживаются на тех яп и технологиях, которые или популярны или по стечению обстоятельств должны использовать только их и никакие иначе, также сюда подключается проблема стоймости разработки, поддержки и переписывания какого-либо уже работающего продукта на непопулярный яп.

В силу недостаточных знаний, в общих чертах я понял Вашу идею. На мой взгляд довольно интересное решение. Очень интересно почитать продолжение Вашей разработки современного web-приложения на Lisp, особенно интересен результат в том на сколько конкурентноспособно будет приложение по сравнению с современными фреймворками🤔 Большой удачи и терпения Вам, надеюсь найдутся компетентные помошники✊

Я не собираюсь конкурировать с другими фреймворками, боже упаси) Вообще, мое глубокое убеждение в том, что с языком, средой и библиотеками не нужно бороться, нужно их использовать! OMG можно прикрутить к любому уже существующему сайту, добавив загрузку одного js-файла и дальше выполнять на странице любой LISP-код, параллельно со всем остальным кодом. Также, поскольку мы имеем полный доступ к DOM и JS, можно использовать любые JS-фреймворки, просто вызывая их функции. Я не стал раздувать статью, но в omgui.lisp есть код, подключающий API YouTube и позволяющий добавить плеер на страницу. То же можно сделать и со всякими React-ами и прочими jquery, не к ночи будь помянуты.

что-то я подзабыл как с quicklisp работать.

(ql:quickload :omg)

System «omg» not found

а может просто нет там омг

(ql:system-apropos «omg»)
ничего не выдаёт.

а как поместить в local-projects не знаю

сейчас там лежит пустой system-index.txt

УПД

надо было сделать (ql:update-dist «quicklisp»)

Sorry

УПД2

И даже всё работает!

Windows 10, sbcl 2.0.0

О! Библиотека работает на Windows! Неожиданно)

Почему бы и нет? У sbcl какие-то проблемы c threading были под windows, вроде бы починили, точно не скажу. А так, если не хотеть чего-нибудь странного… Например omgdaemon — мельком заглянул внутрь. Увидел страшные слова. Типа «докер». И закрыл. Но всё же, думаю, что решаемо.

Просто я ни разу не тестировал на Windows. Та часть, за которую отвечает omgdaemon, практически наверняка не будет работать сейчас ни на чем кроме связки Linux/SBCL и MacOS/SBCL, уж больно она завязана на fork/exec. Но я работаю над этим)

Возможно вас заинтересует PicoLisp (https://picolisp.com), самодостаточный и уже очень давно дружит с вебом и умеет много интересных вещей.

Нууу… Где пико, а где sbcl, практически полная реализация стандарта ANSI с кучей либ, CLOS, компилятором итд итп.

Интересная реализация, спасибо! Но я пока еще не готов заниматься портированием. Есть шанс, конечно, что там всё само заработает, но я сомневаюсь. Похоже, там свой FFI, если он не поддерживается нужными мне пакетами (в основном, clack, bordeaux-threads и пр.), то придется затратить довольно много усилий.

Любопытная статья. Я примерно такое-же реализую, но для Smalltalk.

После создания элемента через OMG он храниться в каком-то серверной версии DOM-дерева? Или всё отправляется в броузер сразу? Как получить у созданного элемента свойство clientHeight/clientWidth через OMG? Надо посылать специальный запрос в броузер?

О, Smalltalk, мое уважение!

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

(let ((el (create-element "div" :|innerHTML| "Hello world!")))
  (ensure-element el ;; execute the following code when the element really appears
    (jslog (jscl::oget el "clientHeight"))))

Если же мне надо будет зачем-то узнать высоту элемента на бэкенде, я должен явно запросить ее у браузера или пусть браузер вызовет RPC и сообщит:

(defun-r rpc-report-height (height)
  (format t "The height is ~A px!~%" height))

(defparameter-f *my-div* nil)

(defun-f get-div-height ()
  (jscl::oget *my-div* "clientHeight"))

(defun-f make-div ()
  (setf *my-div* (create-element "div" :|innerHTML| "Hello world!"))
  (ensure-element *my-div*
    (rpc-report-height (get-div-height)))
  nil)

(make-div) ;; The #'rpc-report-height must be fired
(sleep 1)
(print (get-div-height)) ;; call browser-side function

В принципе, бэкенд не контролирует браузер на 100%, просто дает ему команды и браузер их выполняет. Я даже хочу реализовать "production mode", когда сокет вообще не открывается, а браузер сразу получает весь код, скомпилированный и упакованный, оставив текущую схему для разработки/отладки, а также для приложений, где важна интерактивность.

Ясно.
Честно говоря я слабо знаю Lisp.
Как я понял: создаётся div и сразу после создания на сервер отправляется его clientHeight.
Хорошо. А как запросить у броузера информацию Вы уже продумывали механизм?

Я лично у себя использую websocket-соединение чтоб общаться с броузером. Но он асинхронный. И это создаёт сложности. В данный момент я просто делаю wait в коде пока не придёт ответ от броузера. Других удобных способов я не нашёл пока-что.

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

Попробуй добавить свой проект на мой Ultralisp.org. Там dist будет обновляться сразу после пуша в Git репозиторий.

А ещё хочу упомянуть пару библиотек – Reblocks (она позволяет писать всю бизнес-логику на Common Lisp и запускает её на бэкенде, а на фронт отдаёт команды, как поменять DOM дерево), а так же CLOG – она вроде больше похожа на твой OMGlib, только более продвинутая на данный момент.

Спасибо за наводку! Добавил два проекта в ultralisp, но с OMGlib там проблемы -- возможно, ultralisp не умеет правильно скачивать сабмодули git, а у меня так JSCL добавлен. У JSCL вообще нет asdf и я использую слегка грязноватый хак для того, чтобы включить его в свой пакет (см. omg.asd). С quicklisp это работает.

Что касается Reblocks и CLOG -- я видел эти проекты, хотя и не погружался в них глубоко. Главное отличие OMG -- возможность переноса практически всей интерфейсной логики на сторону клиента, при этом сохраняя единый lisp-образ на сервере, где его можно модифицировать и это сразу* отображается на стороне клиентов. В принципе, если приложение не зависит от бэкенда (например, оно использует API каких-то чужих сервисов), то его можно (пока это не реализовано, правда) вообще отвязать от сервера, сделав автономным.

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

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

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

Да, сейчас Ultralisp.org действительно не выкачивает GIT сабмодули и я не натыкался на проекты которые бы не работали из-за этого :)

Думаю это не сложно будет поддержать. Попробую добавить на днях.

ок. Не забудь реализовать обновление сабмодулей, иногда я так обновляю версию JSCL в OMG)

А вообще идея с использованием JSCL прикольная. У меня для Reblocks иногда приходится писать какой-нибудь JS код, но я для этого использую Parenscript.

Скажи, а как у тебя реализована работа с DOM на стороне клиента? Вызов стандартных JS функций и тд. Я бы с удовольствием тоже заиспользовал JSCL вместо Parenscript.

да прямо как в JS, через FFI JSCL:

((jscl::oget (jscl::%js-vref "document") "body" "appendChild") 
 ((jscl::oget (jscl::%js-vref "document") "createElement") "div"))

Но чтобы не видеть этого безобразия я сделал небольшую библиотечку omgui (часть OMGlib), где это делается так:

(append-element
  (create-element "div" :|innerHTML| "Hello world!"
                        :|style.padding| "1em"
                        :|style.background| "red"))

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

О! Спасибо!
Скрестить бы create-element с Spinneret и LASS – цены бы ему не было!

мой способ гибче:

Sign up to leave a comment.

Articles