LINUX.ORG.RU

Какой из лиспов лучше взять?

 ,


6

4

Собственно меня интересуют батарейки и возможность компиляции в нативный код (последнее в меньшей степени). Как я понял, серьезно следует рассматривать только различные реализации CL и Scheme (Racket).

Если вы предлагаете Clojure, хотелось бы услышать обоснование (кококо-интероперабельность-с-жабой и кококо-ынтырпрайз - не аргументы).

Deleted
Ответ на: комментарий от alienclaster

и может ты мне покажешь хотя бы продакшн-риди веб-сервер на common lisp?

Они есть и работают в независимомти от того назовешь ли ты их этим буржуйским словом или нет. А явовские «продакшн-риди» которым так «славен» clojure никому кроме явистов тоже не нужен.

antares0 ★★★★
()
Ответ на: комментарий от alienclaster

а чего, за 30 лет не смогли написать?

Где-то в начале эпохи web-а их и было до четверти. Если Норвиг нам не врет.

antares0 ★★★★
()
Ответ на: комментарий от anonymous

Это как раз беда.

Нет, не беда. Ведь фактически у нас есть один способ обратиться у слоту переменной и без перекрытия тут не обойтись, как бы. А ты предлагаешь в скоуп подбрасывать какие-то трансформированные идентификаторы, которые не указаны явно и где поведение трансформации зависит от окружения. Так никто не делает. Не уверен, что так долбиться в сраку принято у ракетчиков. Если это действительно так, то ракетчики должны просто сдохнуть.

Ну и все. Тогда смысл такого костыля, если он ничего не дает?

Где ты разглядел костыль, дебилушка? Тут всё чётко на уровне дизайна языка (Lisp 2). Функции, в данном случае, доступны всегда. Ведь не будешь же ты задавать названия полей sql таблиц с учётом функций в твоём окружении. Это же полный бред. Единственный способ наверняка не перекрыть функции — реализовать макрос с необходимостью всегда указывать поле и переменную связанную с ней. А то что ты написал с трансформацией — полная, наркоманская хуйня.

Так в 99% случаев проблема с перекрытием переменных из одного пространства.

Нет. Проблемы с перекрытием переменных особо нет, ведь ты знаешь что у тебя в скоупе и поэтому, если перекрытие не нужно, просто задаёшь связку поле — переменная.

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

Нет. Проектировать макросы подобным образом очень плохо. И дело тут не в «хорошей» или «плохой» макросистеме. И всё тут совершенно не хорошо. Выглядит как «хуй знает когда и при каких обстоятельствах какой скоуп».

Не работает же!

Лол. И что за хуйню ты написал? defun определяет свой скоуп, скоуп do-select расположен над ним и следовательно не виден. Скажи, ракетчики все такие дебилы?

deadlock
()
Ответ на: комментарий от deadlock

А чем плох F#?

Функциональщина, т.е., маргинальщина, т.е., ненужно.

Вполне себе годный современный ML

«Современный» и «ML» в одном предложении не употребляются. Учи грамматику, ламер!

под .net.

Это такой умножитель ненужности на два порядка.

anonymous
()
Ответ на: комментарий от deadlock

Нет, не беда. Ведь фактически у нас есть один способ обратиться у слоту переменной и без перекрытия тут не обойтись, как бы.

Ну как не беда? Ты же сам сказал, что плохо, когда переменные друг друга перекрывают.

А ты предлагаешь в скоуп подбрасывать какие-то трансформированные идентификаторы

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

Функции, в данном случае, доступны всегда.

Ну как же всегда? можно flet'ом перекрыть.

Проблемы с перекрытием переменных особо нет, ведь ты знаешь что у тебя в скоупе и поэтому, если перекрытие не нужно, просто задаёшь связку поле — переменная.

Именно! На самом деле нету никакой проблемы. Ты ее выдумал. И по-этому лисп-2 тут ничего не решает. Ведь решать нечего. Именно об этом я и говорил с самого начала. Хорошо, что ты все понял.

Нет.

Да. Это _единственный_ нетривиальный юзкейс макросов. Если макросы не использовать подобным образом - они становятся вообще ненужны.

Проектировать макросы подобным образом очень плохо. И дело тут не в «хорошей» или «плохой» макросистеме.

Нет, проблема именно в ней. Если макросистема, как в общелиспе, не позволяет удобно работать с подобными макросами - то, конечно, «проектировать так макросы» в ней будет плохо. Это верно для любой фичи в любом языке - если фича в языке поддерживается хуево, то ее использование будет кривое и костыльное, а потому - плохо.

Лол. И что за хуйню ты написал?

Допустим. Ну хотя бы так ведь должно работать?

(let ()
  (defun huy () 
    (do-select% ((id
                foo-bar
                (baz "xyz")
                list)
               :table)
      (+ $id foo-bar baz $list)))
    (defun id () 'yoba))

anonymous
()
Ответ на: комментарий от anonymous

Ох. Нету больше сил :)

Это ты тут нашел проблему и я предложил ее решение - полноценное. В отличии от лисп-2, когда ф-и не перекрываются, а переменные - да.

Это _единственный_ нетривиальный юзкейс макросов. Если макросы не использовать подобным образом - они становятся вообще ненужны.

Забей на Lisp, не пиши на нём ничего. Не твоё, мань... Не твоё.

deadlock
()
Ответ на: комментарий от anonymous

Ну как же всегда? можно flet'ом перекрыть.

Можно. Можно ещё и яйца дверью прищемить. Ты где-нибудь заметил в моём макросе flet?

deadlock
()
Ответ на: комментарий от anonymous

Допустим. Ну хотя бы так ведь должно работать?

Нет, конечно. И не должно. Common Lisp обрабатывает формы в строгой очерёдности.

deadlock
()
Ответ на: комментарий от anonymous

Если макросистема, как в общелиспе, не позволяет удобно работать с подобными макросами - то, конечно, «проектировать так макросы» в ней будет плохо.

Ох, блин. И чем же плоха макросистема CL? Неужели ты очередной петушок с сосача повторяющий одни и те же глупости? Кудахчешь и молишься фазам компиляции ракетки? Ну так я тебе привёл пример интроспекции окружения макросами в CL (с расширением CLtL2). Теперь тебе «не нравиться» система компиляции и загрузки исходников CL. Ну что тут скажешь... Молись дальше.

deadlock
()
Ответ на: комментарий от deadlock

И чем же плоха макросистема CL?

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

Ну так я тебе привёл пример интроспекции окружения макросами в CL

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

anonymous
()
Ответ на: комментарий от deadlock

Нет, конечно. И не должно.

Как же не должно? Ведь в лексическом контексте тела функции, id, очевидно, связана.

anonymous
()
Ответ на: комментарий от deadlock

Можно. Можно ещё и яйца дверью прищемить.

Ну то есть ты понимаешь, что твое: «вот в лисп-1 тут у нас все перекроется, а вот в лисп-2 будет заебись!» - это не более чем визгливое кукареканье, ведь все эти «можно перекрыть» ИРЛ сводятся к защемлению яиц?

anonymous
()
Ответ на: комментарий от deadlock

Забей на Lisp, не пиши на нём ничего. Не твоё, мань... Не твоё.

Ну чего же не мое? Мне интересна тема макросов, так что, как раз, - мое. Только, естественно, нужно выбирать диалект, в котором макросы есть. В отличии от того же общелиспА, где их, по факту, нет.

anonymous
()
Ответ на: комментарий от anonymous

Мне интересна тема макросов, так что, как раз, - мое. Только, естественно, нужно выбирать диалект, в котором макросы есть. В отличии от того же общелиспА, где их, по факту, нет.

Ок, убедил - для тебя в CL макр нет.

yyk ★★★★★
()
Ответ на: комментарий от yyk

При чем тут я? По факту, для всех. Никто же не считает, например, макросы сишки за полноценные макросы? Ну вот макросы общелиспа - то же самое.

anonymous
()
Ответ на: комментарий от anonymous

По факту, для всех.

Перестань натягивать гандон на глобус - он не для этого! У тебя собственные представления о том, какими должны быть макросы и как и где их надо использовать. Так что «по факту» твоё «для всех» - жалкая попытка задрать своё ЧСВ, на деле характеризующая тебя как совершенно бесполезного и неинтересного собеседника, ибо выдавать свои «особенные» мысли за «истину в последней инстанции» - в лучшем случае признак тупого троллинга...

Похоже, я старею: троли всех мастей задрали до такой степени, что я готов голосовать за самую зверскую диктатуру, лишь бы мир наполнился «чистым и непорочным молчанием». Хотя, я знаю что делать - здесь часто что-то говорят про роботов... ;)

yyk ★★★★★
()
Ответ на: комментарий от yyk

Перестань натягивать гандон на глобус - он не для этого!

А для чего? Ведь какую нетривиальную задачу для макросов CL не возьми - она, блять, «не для этого»! «Это плохо», блять!

anonymous
()
Ответ на: комментарий от anonymous

Ты просто ничего не понял в лиспе, лисп не такой, он работает по-другому!!!111

anonymous
()
Ответ на: комментарий от anonymous

А для чего? Ведь какую нетривиальную задачу для макросов CL не возьми - она, блять, «не для этого»! «Это плохо», блять!

Ты это серьёзно? Мы имеем два аналогичных по функциональности макроса на CL и ракетке, я даже пошёл тебе на встречу, и показал пример генерации определений переменных на основании контекста и заметил, что так делать нельзя. Нельзя не из-за CL, а *вообще* нельзя, понимаешь? Из-за не очевидного поведения раскрытия макросов. Как бы тебе объяснить, дурачку! Вот смотри: есть у нас функция «yoba» в окружении, есть и поле «yoba» в запросе do-select. do-select определит, что нужна «YOBA». Окей. Завязались мы в теле на переменную «YOBA». Далее решили, что функция «yoba» нам не нужна — убрали, скомпилили. Йопть. Ошибка. «YOBA» больше в скоупе нет. Если обобщить, то код в теле do-select будет ломаться постоянно при разработки. Ведь контекст постоянно редактируется, меняется.

deadlock
()
Ответ на: комментарий от anonymous

Ну чего же не мое? Мне интересна тема макросов, так что, как раз, - мое.

Не твоё. Ты не понимаешь простых вещей: что можно, а что нельзя. Не знаешь о «POLA» и скорее всего даже не читал классику на тему МП Lisp. CL, Racket, Clojure совершенно ни при чём, если ты сам по себе дебил.

deadlock
()
Ответ на: комментарий от anonymous

Ну то есть ты понимаешь, что твое: «вот в лисп-1 тут у нас все перекроется, а вот в лисп-2 будет заебись!» - это не более чем визгливое кукареканье, ведь все эти «можно перекрыть» ИРЛ сводятся к защемлению яиц?

Я уже заметил, что разделения пространств имён не killer feature, а просто удобная вещь, такая, например, как multiple values. Так и в нашем макросе, повторюсь, можно расслабиться и не задумываться о перекрытии *функций* sql-полями. Тогда как в Lisp-1 задумываться нужно и добавлять формы (var ident) по мере использования в теле, функций совпадающих с sql-полями, а это не удобно. Вот и всё. И где тут «защемление яиц»?

deadlock
()
Ответ на: комментарий от anonymous

При чем тут я? По факту, для всех. Никто же не считает, например, макросы сишки за полноценные макросы? Ну вот макросы общелиспа - то же самое.

Ну уж, ну уж. Пока ты только продемонстрировал синтаксический сахарок, который никак не помог тебе. Твоё решение громоздкое, в сравнении с решением на CL (но я допускаю, что не из-за Racket, а из-за тебя, Мань). Далее ты вскочил на конька «фазы и интроспекция окружения», намекая при это, что, дескать, CL убог и не может. Тогда как CL всегда мог и может :) Забудь ты про статью Fare, Мань, ты же всё равно из неё ничего не понял, кроме последней фразы. Этот товарищ не внимательно читал CLHS и CLtL2 book, вот его и бомбануло.

deadlock
()
Ответ на: комментарий от deadlock

Нельзя не из-за CL, а *вообще* нельзя, понимаешь?

Так я же тебе и объясняю - именно что нельзя из-за CL. Подобные вещи - это _единственный_ юзкейс макросов. Вообще. Если ты утвердаешь, что так делать «нельзя», то это ранвосильно утверждению, что «макросы нинужны».

Из-за не очевидного поведения раскрытия макросов.

Оно вполне очевидно.

Но вообще это разговор бессмысленный - как я уже сказал, никакой проблемы с перекрытием переменных тут нет (и ты, в принципе, с этим согласен), потому и никаких YOBA вместо yoba ИРЛ делать нинужно.

anonymous
()
Ответ на: комментарий от deadlock

Ты не понимаешь простых вещей: что можно, а что нельзя.

А ты не понимаешь зачем нужны макросы, как они используются и какие выразительные средства требуются от макросистемы.

anonymous
()
Ответ на: комментарий от deadlock

Я уже заметил, что разделения пространств имён не killer feature, а просто удобная вещь

Я уже заметил, что даже в lisp in small pieces эта «фича» считается _недостатком_, а не _достоинством_.

Так и в нашем макросе, повторюсь, можно расслабиться и не задумываться о перекрытии

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

Тогда как в Lisp-1 задумываться нужно

Так и в Lisp-2 нужно задумываться и добавлять формы (var ident) для переменных (которые перекрываться будут гораздо чаще ф-й, понятное дело)! При этом задумываться в lisp-2 надо больше - в лисп-1 я точно знаю, что если переменная определена в скопе, то она будет перекрыта. А в лисп-2 хуй его знает. Может перекроется, а может - нет. И если у тебя какая-нибудь (yoba x) - то хуй пойми, из какого скопа будет выбрана «х».

anonymous
()
Ответ на: комментарий от deadlock

Ну уж, ну уж. Пока ты только продемонстрировал синтаксический сахарок

Это не просто синтаксический сахарок. В общелиспе его реализовать нельзя (не переписав макросистему и рантайм, понятное дело, после чего это уже будет не общелисп).

Твоё решение громоздкое

Ну этот твой высер даже не смешон. Мое решение полностью декларативно, проще, вдвое короче, при этом значительно обгоняет твое по реализованному функционалу (если ты попытаешься сделать все, что сделано в моем, то разница будет уже не в два раза, а во все 5).

Далее ты вскочил на конька «фазы и интроспекция окружения», намекая при это, что, дескать, CL убог и не может.

Где? Покажи. Там даже экспандер однопроходной, о чем вообще речь?

anonymous
()

Какой из лиспов лучше взять?

Никакой.

Маргинальные технологии родом из 50-ых годов прошлого века в XXI-м веке не нужны.

anonymous
()
Ответ на: комментарий от anonymous

Это не просто синтаксический сахарок.

В приведенном макросе выглядит как беспонтовый синтаксический сахарок.

В общелиспе его реализовать нельзя (не переписав макросистему и рантайм, понятное дело, после чего это уже будет не общелисп).

Пока не понятно, ради чего. Кроме верчения жопой, баттхёрта и кривой реализации макроса, ты ничего не показал.

Мое решение полностью декларативно

Охуеть, Мань!

проще

Ну да. Ну да. Пока я увидел только: питушиную доработку макроса в плане использования интроспекции окружения в худших традициях, протекающую переменную row (ракетчики, это правда или я чего-то понимаю?) и вот такие-то хуйцы «#`#,» :) Пока не очень прикольно.

вдвое короче

Не пизди, Мань. Выкладывай полное решение на ideone. Сравним.

при этом значительно обгоняет твое по реализованному функционалу

И какая там реализована функциональность коей нет в моей реализации?

если ты попытаешься сделать все, что сделано в моем

А что у тебя сделано, что нет в моей реализации? Расскажи, покажи.

deadlock
()
Ответ на: комментарий от monk

Чуть ли не самый адекватный пост за весь тред.

Стандартно нет. Есть https://github.com/Kalimehtar/gls Позволяет диспатчить методы не только по классам, но и по произвольным типам (то есть произвольным предикатам).

Забавно. Но документации я не нашёл толковой. Сыростью пахнуло :) А можно свой комбинатор написать?

Также, как видно из примера, необязательно делать generic глобальным.

А зачем может понадобиться не глобальный generic?

В явном виде нет. Но любая яконструкция на handler-bind/handler-case/restart достаточно легко реализуется с той же семантикой.

И каким образом? Продолжениями? В любом случает, мне кажется, что тяжко всё это реализовать за вечерок на коленке: http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node312.html#SECTION00330000000....

deadlock
()
Ответ на: комментарий от deadlock

И чем же CL устарел, Вень? Тем, что в стандарте нет ленивых структур данных?

про структуры данных — нерелевантно. но таки стандарт устарел, да. он просто слишком громоздок по сравнению с другими вариантами. его надо было бы упростить, сократить, факторизовать. но всем пофиг.

выразительность решения в первую очередь определена соответствием семантики языка к решаемой проблеме. И именно лаконичность и гомоиконность синтаксиса позволяет сосредоточиться над проектированием самого важного — семантики.

тогда СL просто недостаточно гомоиконен. гораздо более гомоиконен kernel из-за тау-выражений и «вау»-исчисления с eval/operatives вместо eval/apply

anonymous
()
Ответ на: комментарий от deadlock

Ну так что? В каком тут месте преимущество lisp-2 укажешь?

О яебу ты дебил. Десяток строк адекватного кода не CL не осилил. Ты обратил внимание на сущность «list», которая представлена как и в sql запросе, так и в качестве идентификатора переменной lisp? Что будешь делать в lisp-1, а? Напишешь правила трансляции идентификаторов совпадающих со стандартными функциями?

ребяты, мне действительно интересна ваша дискуссия. на тему lisp-n.

давайте устремим это на бесконечность, в пределе. пусть есть некий lisp-n, почему он более полезен обычного lisp-1 (лисп-алеф0 в кодировке Чёрча) из схемки?

пока что мне в голову приходит один вариант. даже два.

1. распознавание естественного языка. например, отцитированное от клинчезатыка:

((оценочное-суждение-обвинение-экспрессия-мат++ ..) (сколько? десяток) (чего? строк (какого? адекватного) кода) (на-чём? (опечатка? не :возможно-правильно на) CL) (что-сделал? не осилил))

((кто? Ты) (что-сделал? обратил внимание) (на-что? на сущность "list" (какая? которая (..-оборот? представлена) (где-локатив? как и (локатив-место? в sql запросе) так и (локатив-качество? в качестве (чего? идентификатора (кому-принадлежит? переменной) (имя? lisp)) )) )))

(вопрос? (что-делать? что (кто? ты) (будущее-время? будешь) делать) (где-локатив? в lisp-1) (усиление?  , а))

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

теперь представьте, что все они живут в отдельных «пространствах имён» в lisp-N.

то есть, по сути аналогичны спец. формам.

и eval/apply или eval/operate в случае kernel и вау-исчисления — связывает различные env таких разных «пространств имён» в одно общее виртуальное пространство, типа как lisp-1 в схеме.

соотв., eval таких форм понимает синтаксис языка.

вопрос, чем такое потенциально лучше чем через ('вопрос? ('что-делать? что ...)) + свой интерпретатор, «парсер ЕЯ»?

чувствую, что возможны более глубокие оптимизации, чем в схемке, с 1 пространством имён. но доказать не могу.

2. так как эти «пространства имён» реализуют кодировку Чёрча, они эквивалентны разным типам данных.

аналогично можно реализовать типизированный лисп.

в котором опять таки понадобятся спец.формы для перевода из lisp-i в «общее универсальное» пространство имён в схемке.

или это уже будут вау-выражения?

опять таки, чувствую что возможны какие-то преимущества с типизацией и вау-выражениями и eval/operative как в kernel.

кто что плохого может сказать про недостатки такого вот lisp-N?

anonymous
()
Ответ на: комментарий от anonymous

Никто не думает о трансляции имен и их ручной обработке. Потому что не бывает таких ситуаций, где это нужно.

зачем их «транслировать»? раскидаем по отдельным «пространствам имён» N для lisp-N. ну будет у нас N отдельных окружений.

теперь свяжем их в одно общее «виртуальное пространство имён» lisp-0.

Потому что не бывает таких ситуаций, где это нужно.

c этим да, use case не очень-то придумывается. разве что лавсановы «кластеры метапарадигм», ага :)

lisp-N как мультистадийный лисп с частичными вычислениями в различных N окружениях, связанных в единую гиперсеть по разному (кодировка Чёрча) типизированных данных

anonymous
()
Ответ на: комментарий от deadlock

Но документации я не нашёл толковой. Сыростью пахнуло :) А можно свой комбинатор написать?

По использованию есть только https://github.com/gregsgit/glos/blob/master/ref-dyn-patterns.pdf — что-то вроде дипломной работы автора этой штуки.

Комбинатор написать можно: в https://github.com/Kalimehtar/gls/blob/master/gls/callables.rkt есть примеры. Только в API не вынесено. По-нормальному надо добавлять параметр к make-generic. Сейчас для своего комбинатора придётся писать свой

(define (make-my-generic name . methods)
  (let ((gf (really-make-generic name methods
my-composer standard-add-method-check)))
    (for-each (lambda (m)
(set-method-generic/f! m gf))
methods)
    gf))

А зачем может понадобиться не глобальный generic?

Затем же, зачем и не глобальная функция. Например:

;; my-plugin.rkt
(provide register)

(define (register generic)
   (add-method generic
      (method ((common-object enterprise-object%) 
               (item my-item%))
         ....)))

;; main.rkt
(require (prefix-in p1: my-plugin) 
         (prefix-in p2: another-alternative-plugin))

(defgeneric processor ...)

(if (something)
  (p1:register processor)
  (p2:register processor))

И каким образом? Продолжениями? В любом случает, мне кажется, что тяжко всё это реализовать

Да не надо это всё реализовывать. Так же как не надо на CLOS писать реализацию семантики C++ классов с шаблонами. Любая реальная задача, удобно решаемая на сигнальном протоколе так же легко решается на исключениях + продолжениях.

monk ★★★★★
()
Ответ на: комментарий от deadlock

твой кусок кода отсюда для CL, кстати, напоминает то, как прокидываются opertatives в evalы для выу-выражений.

толи отсюда, то ли отсюда

скорее второе, про определения quote,list,bind, eval и т.п.

сдаётся, пишешь руками код, у которого есть более общий паттерн в вау-выражениях.

anonymous
()
Ответ на: комментарий от anonymous

Любой, кто видел нормальные ЯП, и посмотрит на язык, в котором факториал пишется в сотню строк, скажет, очевидно: «ваш язык говно». Вот и тут та же логика.

как будто что-то плохое.

вот по-настоящему тяжёлый случай

To test this, we need to go deeper.

...

This is factorial implemented in Scheme, implemented as a library for Qoppa, implemented in Scheme, implemented as a library for Qoppa, implemented in Scheme (implemented in C). Of course it's outrageously slow; on my machine this (fact 5) takes about 5 minutes. But it demonstrates that a tiny language of operatives, augmented with an appropriate library, can provide enough syntactic features to run a non-trivial Scheme program. As for how to do this efficiently, well, I haven't got far enough into the literature to have any idea.

отсюда

осталось придумать, как это можно обернуть на пользу

anonymous
()
Ответ на: комментарий от anonymous

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

всё равно они должны (если должны) перекрываться не все вообще абы как, а с учётом модульности.

anonymous
()
Ответ на: комментарий от anonymous

А в лисп-2 хуй его знает. Может перекроется, а может - нет. И если у тебя какая-нибудь (yoba x) - то хуй пойми, из какого скопа будет выбрана «х».

ок, возьмём гипотетический lisp-N с lisp-0.

в lisp-0 смотрим (yoba x). оно раскрывается в (lispK yoba X). значит, ищётся по умолчанию в K-м «пространстве имён».

а где-то ещё рядом с определением lisp-0 задаются правила: (lispK=2-func yoba (lisp1-var x)) или (lispM=5-macros yoba (lisp1-var x)) или (lispS-9-specforms yoba (lisp1-var x))

с возможностью по ходу дела эти правила и порядок их вычисления переопределять.

каковы минусы такой схемы?

anonymous
()
Ответ на: комментарий от deadlock

В приведенном макросе выглядит как беспонтовый синтаксический сахарок.

Но в общелиспе он нереализуем.

Пока не понятно, ради чего.

Для того, чтобы вместо костыльного говна писать короткий, функциональный, понятный код.

Пока я увидел только: питушиную доработку макроса в плане использования интроспекции окружения в худших традициях

При чем тут интроспекция? Мы, вроде, уже решили, что ИРЛ никакой интроспекции тут будет не нужно, ведь никакой проблемы перекрывающихся идентификаторов на деле не существует. Я про это решение, которое аналог исходного:

(begin-for-syntax
  (define-syntax-class binding #:auto-nested-attributes
    (pattern (id:id str:str))
    (pattern id:id
             #:with str #`#,(let ([s (symbol->string (syntax-e #'id))])
                              (string-replace (if (sequence-ormap char-lower-case? s)
                                                  s
                                                  (string-downcase s))
                                              "-" "_"))))
  
  (define (get-sql bstrs table)
    (~a "SELECT " (apply ~a bstrs #:separator ", ") " FROM " table)))

(define-simple-macro (do-select ((b:binding ...) table:binding) body:expr ...+)
  #:with sql #`#,(get-sql (syntax->datum #'(b.str ...)) (syntax-e #'table.str))
  (with-rows ([row sql])
     (match row 
       [(list b.id ...) body ...])))

протекающую переменную row

Это тебе не общелисп, тут ничего не протекает и just works. Гигиена же.

и вот такие-то хуйцы «#`#,»

Это оборачивание константы в синтаксический объект. Ну как `,.

Выкладывай

Дык выложил.

И какая там реализована функциональность коей нет в моей реализации?

Обработка ошибок, например:

(do-select ((id
            foo-bar
            (baz 2)
            list)
            table)
    (do-something id foo-bar baz list))

->
.rkt:33:17: do-select: expected string at: 2 in: (do-select ((id foo-bar (baz 2) list) table) (do-something id foo-bar baz list))

anonymous
()
Ответ на: комментарий от deadlock

А зачем может понадобиться не глобальный generic?

Ну, например, какой-нибудь макрос можно достаточно просто реализовать через объявление внутреннего для макроса генерика и его использования. Если генерик будет глобальный - нам будет засирать глобальный неймспейс/память при вызове макроса в локальном контексте, хотя это нинужно.

И каким образом? Продолжениями?

Да.

В любом случает, мне кажется, что тяжко всё это реализовать за вечерок на коленке:

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

anonymous
()
Ответ на: комментарий от anonymous

в lisp-0 смотрим (yoba x). оно раскрывается в (lispK yoba X).

А я когда использую макрос, то не знаю, во что он раскрывается и знать не должен. Так же как я не должен знать, как именно реализована та или иная библиотечная ф-я, которую я использую. Если приходится знать - абстракция течет.

anonymous
()
Ответ на: комментарий от anonymous

Обработка ошибок, например

Внезапно:

(do-select ((id
             foo-bar
             (baz 2)
             list)
            :table)
  (do-something id foo-bar baz list))

;; (BAZ 2) fell through ETYPECASE expression.
;; Wanted one of ((CONS SYMBOL (CONS STRING NULL)) SYMBOL).
;;    [Condition of type SB-KERNEL:CASE-FAILURE]
Ещё какая функциональность в примере на CL «не реализована»?

Но в общелиспе он нереализуем.

Что? Что именно делают эти анальные игрушки? Расскажи, подробнее. Пока твой макрос ничего не показал.

Это тебе не общелисп, тут ничего не протекает и just works. Гигиена же.

Ok.

Это оборачивание константы в синтаксический объект. Ну как `,.

Ok.

deadlock
()
Ответ на: комментарий от anonymous

А я когда использую макрос, то не знаю, во что он раскрывается и знать не должен. Так же как я не должен знать, как именно реализована та или иная библиотечная ф-я, которую я использую. Если приходится знать - абстракция течет.

Хорошие слова. Правильные.

deadlock
()
Ответ на: комментарий от anonymous

При чем тут интроспекция? Мы, вроде, уже решили, что ИРЛ никакой интроспекции тут будет не нужно

Оукей. Слава яйцам.

ведь никакой проблемы перекрывающихся идентификаторов на деле не существует.

Это не проблема. Просто вопрос удобства. Повторю последний раз: если тебе нужно запросить поле «list» и в теле необходимо будет использовать функцию list, ты скажешь: (LIST «list»). Я же оставлю как есть и всё будет работать замечательно :) И я считаю это преимуществом Lisp-2(n).

deadlock
()
Ответ на: комментарий от anonymous

Для того, чтобы вместо костыльного говна писать короткий, функциональный, понятный код.

Приведенный код на CL — короткий, понятный, функциональный :) Что ты имеешь ввиду под костылями? Что именно не так и как должно быть по твоему? Просто ты говоришь, как фанбой пропитанный каким-то маркетинговым bullshit-ом — оперируешь крайне абстрактными и субъективными понятиями.

deadlock
()
Ответ на: комментарий от deadlock

Внезапно:

О чем и речь - где-то что как-то непонятно распидорасило. Хотелось бы нормальное сообщение об ошибке. Указать позицию некорректного терма я уж не прошу.

Что?

В общелишпике нету гигиены, при использовании сложных паттернов и macro-generated macro все пойдет по пизде, это во-первых. Во-вторых, общелишпик не может в нормальную работу с лексическими областями, например, класс определенный в локальном контексте и _должен_ оставаться в локальном контексте - общелишпик cannot into, у него же макрообъявления глобальные.

Опять же, те же взаимнорекурсивные классы, например - общелишпик cannot into, так как экспандер однопроходной. Тут, ты сам понимаешь, ничего не сделаешь, не меняя существенно алгоритм экспандера, а это потянет качественное изменение всей семантики общелиспа - он ведь раскрывает и выполняет формы строго по порядку.

Нормальное позиционирование ошибок - ну это заслуга syntax objects, которые хранят информацию о позиции терма.

Возможность ассоциации с идентификатором статической информации (и потом ее использование, офк), при этом все корректно работает с лексическим скопом - собсно оноа на основе этого и работает. Общелишпик тоже cannot into, если не переопределить все связывающие формы.

И это навскидку.

anonymous
()
Ответ на: комментарий от deadlock

Это не проблема. Просто вопрос удобства.

Этот вопрос удобства был бы решен, если бы каким-то чудесным образом нам было гарантировано отсутствие перекрытия в общем случае. Но ИРЛ у нас имена из макроса будут перекрываться с именами переменных (гораздо чаще, чем с именами ф-й) и нам все равно придется указывать альтернативные имена.

Не говоря о том, что вообще иметь символы, которые в зависимости от позиции имеют разную семантику - это плохая идея. Обычно, когда есть существенная разницу между «видами» переменных, то это выделяется синтаксически - например, переменные могут начинаться только с маленькой буквы, а типы - только с большой. При этом с одной стороны никаких пересечений - с другой стороны, никакой нетривиальной неоднозначности.

anonymous
()
Ответ на: комментарий от deadlock

Что ты имеешь ввиду под костылями?

Под костылями я имею ввиду, например, ручное перепидорашивание списков вида syms (mapcar #'binding->symbol bindings), которое, конечно, работает в тривиальном случае (a ...), но превращается в жуткое говно при хоть сколько-нибудь менее тривиальном паттерне, типа ((a (b c ...)) ...). Или поебень типа:

(defun binding->ident (binding)
  (etypecase binding
    (symbol
     (normalize
      (let ((s (string binding)))
        (if (some #'lower-case-p s)
            s
            (string-downcase s)))))
    ((cons symbol (cons string null))
     (second binding))))

(defun binding->symbol (binding)
  (etypecase binding
    (symbol
     binding)
    ((cons symbol (cons string null))
     (first binding))))

Это когда у тебя два паттерна с парой аттрибутов в каждом - разница по бойлерплейту всего вдвое. А если у тебя с десяток паттернов, по пять атрибутов в каждом, как будет при реализации какого-нибудь лупа? 5 ф-й по 10 кейзов в каждой? А часто может оказаться, что сама по себе попытка выразить паттерн через typecase будет выглядеть как жуткое говно.

anonymous
()
Ответ на: комментарий от deadlock

Чтобы тебе было понятнее, вот этот код:

(defun binding->ident (binding)
  (etypecase binding
    (symbol
     (...)
    ((cons symbol (cons string null))
     (second binding))))

(defun binding->symbol (binding)
  (etypecase binding
    (symbol
     binding)
    ((cons symbol (cons string null))
     (first binding))))
это в точности это:
(define-syntax-class binding 
    (pattern (id:id str:str)
    (pattern id:id
             #:with str (...))))
код, на месте многоточия, практически совпадает (т.к. он к макросистеме не имеет отношения)

Чтобы не увидеть, на сколько второй вариант понятнее и лаконичнее - надо быть полным уебаном.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.