Спасибо за наводку! Добавил два проекта в ultralisp, но с OMGlib там проблемы -- возможно, ultralisp не умеет правильно скачивать сабмодули git, а у меня так JSCL добавлен. У JSCL вообще нет asdf и я использую слегка грязноватый хак для того, чтобы включить его в свой пакет (см. omg.asd). С quicklisp это работает.
Что касается Reblocks и CLOG -- я видел эти проекты, хотя и не погружался в них глубоко. Главное отличие OMG -- возможность переноса практически всей интерфейсной логики на сторону клиента, при этом сохраняя единый lisp-образ на сервере, где его можно модифицировать и это сразу* отображается на стороне клиентов. В принципе, если приложение не зависит от бэкенда (например, оно использует API каких-то чужих сервисов), то его можно (пока это не реализовано, правда) вообще отвязать от сервера, сделав автономным.
Вообще, изначально, я хотел сделать что-то более общее, когда есть мастер-образ lisp, который передает lisp-код в подчиненные lisp-образы, которые запущены на клиентах (например, в мобильниках) и код там выполняется, отрисовывая интерфейсы и исполняя всю интерфейсную логику, какую возможно, локально. Это не обязательно могут быть интерфейсы, скажем, можно так подключить lisp-образы, запускаемые в контейнерах на удаленных серверах и производить там всякие тяжелые вычисления по мере надобности. То есть ботнет-подобная сеть, по сути, но используемая в мирных целях).
Благодаря особенностям Lisp (потому я и выбрал этот язык, хотя слабо им владею) можно всё это делать внутри одного образа, писать, по сути, сплошной код, помечая лишь определенные функции, как выполняемые где-то еще. Пока что эта идея еще в зачаточном состоянии, в основном потому, что у меня нет прикладной задачи, где можно было бы ее применить в полном объеме, но когда такая задача появится, я ее разовью дальше)
Также этот подход (хоть и менее удобно) можно применить в питоне, например, там есть компилятор в JS и можно получить доступ к синтаксическому дереву. Но я не хочу быть тем, кто откроет ящик Пандоры, дав питонистам в руки такую технологию)
А можете вкратце объяснить (или ткните носом в ссылку, плиз) как работает оффлайн-оплата криптой? Ведь я могу сделать полную копию (до бита) своего кошелька, оплатить покупку в одном месте, восстановиться из копии и оплатить в другом теми же деньгами. Если у второго продавца нет доступа к онлайн, то он же никак не может узнать, что я плачу уже потраченными монетами?
Изучать новое всегда полезно, кто бы спорил. Просто в слово "изучать" разными людьми вкладывается разный смысл. В том же Lisp можно такой фортрановский код писать при желании, что ой. Джун, успешно запустивший написавший программу на Scheme и запустивший ее может сказать "я изучил Scheme", но, фактически, может оказаться, что он выучил только синтаксис, а о существовании функционального подхода даже и не догадывается. Изучать надо не Scheme, а SICP, вот что я хотел сказать.
Когда-то я сел подсчитывать, сколько разных языков программирования мне приходилось использовать в жизни. Что-то полезное я писал, кажется, на 15 разных языках, а "потрогать руками" пробовал 20+. И вот что я вам скажу. Языков много, но подходов к программированию, по сути, всего три: функциональное, императивное и другое (тут я смешиваю в одну кучу декларативное и всю экзотику типа verilog/VHDL). Изучив несколько языков, но применяя в них только, например, императивный подход, вы не вырастете ни на миллиметр, развитие, оно не в том, чтобы запомнить новый синтаксис и научиться запускать компилятор. Изучайте не языки, изучайте парадигмы.
Маленькая байка. В самом начале нулевых я, аспирант второго года, решил немного подзаработать. Мне нужен был мопед и не хватало 500 баксов (большие деньги по тем временам). Через знакомого в IRC (тогда всё так делалось) нашлась халтурка -- надо было сделать систему по приему платежей за мобилную связь. Это сейчас можно оплатить телефон не поднимая пятую точку с дивана, а тогда надо было пойти 5 километров в гору в ближайший салон и там твои наличные конвертируются в у.е. на счету мобильного. У фирмы, которой меня сосватали, был диллерский вход на сервера всяких MTS и Билайнов, но они опасались давать его всем работникам на точках приема платежей. За пару недель я настроил им сервер на FreeBSD (линукс тогда не принимали всерьез), написал фронтенд на PHP и бэк на Perl, который пропихивал платежи на сервера операторов, имитируя веб-сессию диллерского интерфейса. Казалось бы, что тут может пойти не так? Я забыл спросить, сколько у этой фирмы точек в Москве. Нет, моя система работала как швейцарские часы. Но начал падать сервер MTS, куда мой бэк пытался запихивать все приходящие платежи в параллель)
примерно. Но этот JS можно обновлять в любой момент, он может учитывать параметры устройства клиента, его историю, локальные данные, что угодно. Фактически, я вообще вернулся к самым истокам истоков -- я могу написать функцию, которая будет получать размеры экрана и рисовать все элементы на нужных местах, как в олдскульных библиотеках интерфейсов)
производительность, кстати, нормальная. Когда в первый раз подгружается весь код, может немного подфризить, но не критично. Зато потом этот код вызывается и отрабатывает мгновенно. При этом не обязательно передавать весь контент каждый раз, можно вызывать функцию с параметром для перерисовки виджета, можно вообще сделать ее автономной, чтобы она сама подгружала что нужно через асинхронные вызовы.
Sorry за саморекламу, но у меня есть концепция по развитию этой идеи :)
Суть в том, чтобы отказаться от JSON вообще, а передавать на устройство прямо код, который оно будет исполнять (в моем случае -- это JS, передаваемый в браузер через вебсокет). Код может не просто отрисовывать элементы, но и определять новые функции, так что можно просто передать клиенту функцию для отрисовки сложного элемента (включая всю внутреннюю логику его работы и всякие анимации/переходы), а потом просто вызывать ее. Или пусть он сам ее вызывает по событию. У меня это реализовано на Common Lisp (извините :), который компилируется в JS, но можно и для других языков это сделать.
Вот уж что действительно не поможет ситуации, так это вынос дискуссии за пределы научного сообщества, на площадки типа Хабра и пр. Возьмем эту статью, например. Один из параграфов -- откровенная манипуляция: Горькавый (если что, я знаю его лично и уважаю) забанен в astroph, все знают Горькавого, значит astroph не прав и всё плохо. А если бы было написано, что лжеученый из Китая Ли Фу Фу забанен на известном международном сайте препринтов за лженаучные статьи якобы опровергающие доказанные теории инфляции, то же самое действие было бы в глазах общественности оправдано. Вообще, arXiv.org это та еще помойка, но к делу это не относится. Научные проблемы должны решаться научными методами и внутри научного сообщества. Химики должны разбираться с химиками, математики -- с математиками. С каждым случаем надо разбираться отдельно, читать и анализировать статьи, писать аргументированные рецензии, спорить и задавать вопросы на конференциях (они для этого и проводятся). Общественное обсуждение же стоит ровно ничего, так как все его участники даже обсуждаемых статей не читали, а если читали, вряд ли поняли хотя бы половину слов.
У меня, собственно, нет никаких особых протоколов общения -- я через вебсокет посылаю в браузер JS-код, браузер его выполняет и возвращает ответ через тот же вебсокет, всё. А уж код может создать элемент, вернуть высоту элемента, всё что угодно. Код пишется тоже на лиспе и потом компилируется (на хосте) в JS перед отправкой.
Элемент создается кодом, который выполняется в браузере, соответственно, он хранится в браузере и больше нигде. Можно сохранить ссылку на этот объект и использовать ее для получения свойств:
(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", когда сокет вообще не открывается, а браузер сразу получает весь код, скомпилированный и упакованный, оставив текущую схему для разработки/отладки, а также для приложений, где важна интерактивность.
когда к ним с замечаниями и предложениями приходит другой такой "старшевозрастной программист"
...вы можете через некоторое время наблюдать двух сильно нетрезвых программистов, стоящих в коридоре в обнимку (чтобы не упасть) и обсуждающих какие-то высокие материи))
я могу сказать, почему Сережа не пишет сразу подсистему ролей -- потому что эта подсистема клиенту не нужна и у клиента возникнет закономерный вопрос, почему он должен платить за разработку ненужного ему кода. Если ему впоследствии потребуется система ролей, то Сережа напишет и ее. Но, из вашего же примера видно, что система ролей не нужна и в последствии. Если у клиента 2 (два) оператора и одному надо запретить определенные действия в воскресенье утром, то городить отдельную таблицу, придумывать интерфейс к ней, прописывать права доступа уже к этому всему (еще одна система ролей?!), обучать клиента работе с ней, писать документацию, чтобы клиент в красивой форме вписал это правило и забыл про нее на следующие 10 лет -- оверкил. Сережа прав.
ок. Не забудь реализовать обновление сабмодулей, иногда я так обновляю версию JSCL в OMG)
да прямо как в JS, через FFI JSCL:
Но чтобы не видеть этого безобразия я сделал небольшую библиотечку omgui (часть OMGlib), где это делается так:
Можно сохранять полученные DOM-элементы в локальных (внутри браузера) переменных и потом с ними делать что угодно.
Спасибо за наводку! Добавил два проекта в ultralisp, но с OMGlib там проблемы -- возможно, ultralisp не умеет правильно скачивать сабмодули git, а у меня так JSCL добавлен. У JSCL вообще нет asdf и я использую слегка грязноватый хак для того, чтобы включить его в свой пакет (см. omg.asd). С quicklisp это работает.
Что касается Reblocks и CLOG -- я видел эти проекты, хотя и не погружался в них глубоко. Главное отличие OMG -- возможность переноса практически всей интерфейсной логики на сторону клиента, при этом сохраняя единый lisp-образ на сервере, где его можно модифицировать и это сразу* отображается на стороне клиентов. В принципе, если приложение не зависит от бэкенда (например, оно использует API каких-то чужих сервисов), то его можно (пока это не реализовано, правда) вообще отвязать от сервера, сделав автономным.
Вообще, изначально, я хотел сделать что-то более общее, когда есть мастер-образ lisp, который передает lisp-код в подчиненные lisp-образы, которые запущены на клиентах (например, в мобильниках) и код там выполняется, отрисовывая интерфейсы и исполняя всю интерфейсную логику, какую возможно, локально. Это не обязательно могут быть интерфейсы, скажем, можно так подключить lisp-образы, запускаемые в контейнерах на удаленных серверах и производить там всякие тяжелые вычисления по мере надобности. То есть ботнет-подобная сеть, по сути, но используемая в мирных целях).
Благодаря особенностям Lisp (потому я и выбрал этот язык, хотя слабо им владею) можно всё это делать внутри одного образа, писать, по сути, сплошной код, помечая лишь определенные функции, как выполняемые где-то еще. Пока что эта идея еще в зачаточном состоянии, в основном потому, что у меня нет прикладной задачи, где можно было бы ее применить в полном объеме, но когда такая задача появится, я ее разовью дальше)
Также этот подход (хоть и менее удобно) можно применить в питоне, например, там есть компилятор в JS и можно получить доступ к синтаксическому дереву. Но я не хочу быть тем, кто откроет ящик Пандоры, дав питонистам в руки такую технологию)
А можете вкратце объяснить (или ткните носом в ссылку, плиз) как работает оффлайн-оплата криптой? Ведь я могу сделать полную копию (до бита) своего кошелька, оплатить покупку в одном месте, восстановиться из копии и оплатить в другом теми же деньгами. Если у второго продавца нет доступа к онлайн, то он же никак не может узнать, что я плачу уже потраченными монетами?
Изучать новое всегда полезно, кто бы спорил. Просто в слово "изучать" разными людьми вкладывается разный смысл. В том же Lisp можно такой фортрановский код писать при желании, что ой. Джун, успешно запустивший написавший программу на Scheme и запустивший ее может сказать "я изучил Scheme", но, фактически, может оказаться, что он выучил только синтаксис, а о существовании функционального подхода даже и не догадывается. Изучать надо не Scheme, а SICP, вот что я хотел сказать.
Когда-то я сел подсчитывать, сколько разных языков программирования мне приходилось использовать в жизни. Что-то полезное я писал, кажется, на 15 разных языках, а "потрогать руками" пробовал 20+. И вот что я вам скажу. Языков много, но подходов к программированию, по сути, всего три: функциональное, императивное и другое (тут я смешиваю в одну кучу декларативное и всю экзотику типа verilog/VHDL). Изучив несколько языков, но применяя в них только, например, императивный подход, вы не вырастете ни на миллиметр, развитие, оно не в том, чтобы запомнить новый синтаксис и научиться запускать компилятор. Изучайте не языки, изучайте парадигмы.
Маленькая байка. В самом начале нулевых я, аспирант второго года, решил немного подзаработать. Мне нужен был мопед и не хватало 500 баксов (большие деньги по тем временам). Через знакомого в IRC (тогда всё так делалось) нашлась халтурка -- надо было сделать систему по приему платежей за мобилную связь. Это сейчас можно оплатить телефон не поднимая пятую точку с дивана, а тогда надо было пойти 5 километров в гору в ближайший салон и там твои наличные конвертируются в у.е. на счету мобильного. У фирмы, которой меня сосватали, был диллерский вход на сервера всяких MTS и Билайнов, но они опасались давать его всем работникам на точках приема платежей. За пару недель я настроил им сервер на FreeBSD (линукс тогда не принимали всерьез), написал фронтенд на PHP и бэк на Perl, который пропихивал платежи на сервера операторов, имитируя веб-сессию диллерского интерфейса. Казалось бы, что тут может пойти не так? Я забыл спросить, сколько у этой фирмы точек в Москве. Нет, моя система работала как швейцарские часы. Но начал падать сервер MTS, куда мой бэк пытался запихивать все приходящие платежи в параллель)
только цифровые!
примерно. Но этот JS можно обновлять в любой момент, он может учитывать параметры устройства клиента, его историю, локальные данные, что угодно. Фактически, я вообще вернулся к самым истокам истоков -- я могу написать функцию, которая будет получать размеры экрана и рисовать все элементы на нужных местах, как в олдскульных библиотеках интерфейсов)
производительность, кстати, нормальная. Когда в первый раз подгружается весь код, может немного подфризить, но не критично. Зато потом этот код вызывается и отрабатывает мгновенно. При этом не обязательно передавать весь контент каждый раз, можно вызывать функцию с параметром для перерисовки виджета, можно вообще сделать ее автономной, чтобы она сама подгружала что нужно через асинхронные вызовы.
Sorry за саморекламу, но у меня есть концепция по развитию этой идеи :)
Суть в том, чтобы отказаться от JSON вообще, а передавать на устройство прямо код, который оно будет исполнять (в моем случае -- это JS, передаваемый в браузер через вебсокет). Код может не просто отрисовывать элементы, но и определять новые функции, так что можно просто передать клиенту функцию для отрисовки сложного элемента (включая всю внутреннюю логику его работы и всякие анимации/переходы), а потом просто вызывать ее. Или пусть он сам ее вызывает по событию. У меня это реализовано на Common Lisp (извините :), который компилируется в JS, но можно и для других языков это сделать.
как они проведут проверку, если инстаграм заблокирован?
А как работает трехфазное УЗО? Если я правильно понимаю, в случае баланса трех фаз через ноль ток может вообще не идти.
А есть ли где-нибудь рейтинг рейтингов? По какому принципу он составляется?
Вот уж что действительно не поможет ситуации, так это вынос дискуссии за пределы научного сообщества, на площадки типа Хабра и пр. Возьмем эту статью, например. Один из параграфов -- откровенная манипуляция: Горькавый (если что, я знаю его лично и уважаю) забанен в astroph, все знают Горькавого, значит astroph не прав и всё плохо. А если бы было написано, что лжеученый из Китая Ли Фу Фу забанен на известном международном сайте препринтов за лженаучные статьи якобы опровергающие доказанные теории инфляции, то же самое действие было бы в глазах общественности оправдано. Вообще, arXiv.org это та еще помойка, но к делу это не относится. Научные проблемы должны решаться научными методами и внутри научного сообщества. Химики должны разбираться с химиками, математики -- с математиками. С каждым случаем надо разбираться отдельно, читать и анализировать статьи, писать аргументированные рецензии, спорить и задавать вопросы на конференциях (они для этого и проводятся). Общественное обсуждение же стоит ровно ничего, так как все его участники даже обсуждаемых статей не читали, а если читали, вряд ли поняли хотя бы половину слов.
У меня, собственно, нет никаких особых протоколов общения -- я через вебсокет посылаю в браузер JS-код, браузер его выполняет и возвращает ответ через тот же вебсокет, всё. А уж код может создать элемент, вернуть высоту элемента, всё что угодно. Код пишется тоже на лиспе и потом компилируется (на хосте) в JS перед отправкой.
О, Smalltalk, мое уважение!
Элемент создается кодом, который выполняется в браузере, соответственно, он хранится в браузере и больше нигде. Можно сохранить ссылку на этот объект и использовать ее для получения свойств:
Если же мне надо будет зачем-то узнать высоту элемента на бэкенде, я должен явно запросить ее у браузера или пусть браузер вызовет RPC и сообщит:
В принципе, бэкенд не контролирует браузер на 100%, просто дает ему команды и браузер их выполняет. Я даже хочу реализовать "production mode", когда сокет вообще не открывается, а браузер сразу получает весь код, скомпилированный и упакованный, оставив текущую схему для разработки/отладки, а также для приложений, где важна интерактивность.
можно и совместить!
...вы можете через некоторое время наблюдать двух сильно нетрезвых программистов, стоящих в коридоре в обнимку (чтобы не упасть) и обсуждающих какие-то высокие материи))
я могу сказать, почему Сережа не пишет сразу подсистему ролей -- потому что эта подсистема клиенту не нужна и у клиента возникнет закономерный вопрос, почему он должен платить за разработку ненужного ему кода. Если ему впоследствии потребуется система ролей, то Сережа напишет и ее. Но, из вашего же примера видно, что система ролей не нужна и в последствии. Если у клиента 2 (два) оператора и одному надо запретить определенные действия в воскресенье утром, то городить отдельную таблицу, придумывать интерфейс к ней, прописывать права доступа уже к этому всему (еще одна система ролей?!), обучать клиента работе с ней, писать документацию, чтобы клиент в красивой форме вписал это правило и забыл про нее на следующие 10 лет -- оверкил. Сережа прав.