LINUX.ORG.RU

Allegro CL 9.0 Free Express Edition стал доступен для загрузки

 ,


9

10

Для загрузки на попробовать стала доступна версия коммерческой реализации языка программирования Common Lisp — Allegro CL 9.0 Express Edition.

Доступны пакеты для:

  • Linux (glibc 2.11 или позже);
  • Mac OS X (10.6 или позже), включает поддержку Lion;
  • FreeBSD (8.2 или позже);
  • Windows (XP, Vista, 7, 8, Server).

Основные новшества и изменения в этой версии:

  • полная поддержка SMP;
  • 820 исправлений и улучшений с последнего релиза;
  • полностью обновлен AllegroServe — вебсервер Franz Inc., написанный на лиспе: автоматическая компрессия/декомпрессия файлов, поддержка chunking, новый выбор опций безопасности, включая TLS v1.0 (также известный как SSL v3.1) протокол для защищенных соединений;
  • улучшена интеграция с Java через модуль jLinker, улучшен протокол, стал проще API;
  • новая и значительно упрощенная инсталляция для графических утилит на Mac 64-бит.

>>> Загрузка

★★

Проверено: anonymous_incognito ()
Последнее исправление: tazhate (всего исправлений: 4)
Ответ на: комментарий от anonymous

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

Никто кроме тебя понятия не имеет, что заложено в твой код. Четко опиши что хочешь увидеть от CL решения.

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

Это схема, сделанная правильно

И, насколько я понял, они поддерживают #r5rs?

Какого рода неожиданностей?

Ну, знаешь, как бывает: «посоны, мы тут внезапно осознали, что все ети годы жили неправильно. Долой!» Конечно, их история не предполагает подбного неадеквата, но что-то уж слишком часто последнее время такая фигня случается, на, казалось бы, совершенно ровном месте. Нехотеть.

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

Нет.

а да, ты только про 99% писал.

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

И, насколько я понял, они поддерживают #r5rs?

В качестве #lang'a да, но racket как язык полным суперсетом r5rs не является (есть некоторые несовместимости).

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

Четко опиши что хочешь увидеть от CL решения.

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

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

Да, как #lang вполне достаточно.

Тогда внутри r5rs-модуля никаких проблем не будет. Но если мешать ф-и из r5rs-модуля и из racket-модуля, то надо учесть, что в первом пары - мутабельные, а во втором - иммутабельные, соответственно, ф-и при импорте надо будет обернуть враппером.

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

с тобой можно как-то связаться?

Да. 31415anon31415@gmail.com

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

Никто кроме тебя понятия не имеет, что заложено в твой код. Четко опиши что хочешь увидеть от CL решения.

Я понял, что он хочет увидеть, но мне пример писать лень (машину купил, голова другим забита). Чтобы так же красиво выглядело, надо будет DSL сочинять.

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

Я понял, что он хочет увидеть, но мне пример писать лень (машину купил, голова другим забита). Чтобы так же красиво выглядело, надо будет DSL сочинять.

Собственно, опуская ДСЛ, у вас будут две ключевые трудности - отсутствие source (а значит корректно указать кусок выражения, в котором ошибка синтаксиса, вы не сможете, то есть вообще никак, хоть упишитесь дслями) и отсутствие в общелиспе поддержки статической информации. Скорее всего, вы соорудите какой-нибудь хеш и будете туда совать при вызове struct нужную информацию и смотреть ее при вызове match (так это всегда и делают в общелиспе). И, естественно, работать это не будет. А альтернативных средств CL не предоставляет.

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

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

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

Да, этот момент я прохлопал. Спасибо

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

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

http://www.cliki.net/pattern matching

И, естественно, работать это не будет.

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

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

Есть две формы - одна определяет некоторую структуру, другая позволяет матчить по этим структурам значение

Просто море либ для CL.

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

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

Все должно работать корректно в смысле лексической структуры программы,

задача компилятора.

а сообщения об ошибках должны выдаваться адекватно, не в виде полотнищ раскрытого кода, как это обычно делается в общелиспе.

макросы их синтаксис к языку отношения не имеет. какие захочешь - такие ошибки и выдавай.

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

в схеме, да, нельзя.

Можно, конечно.

приходится любую элементарную функцию для работы с ними ещё раз приписывать всякими define-syntax специально для макросов.

Нет, не приходится. просто берешь и используешь эту любую функцию. Никаких проблем.

http://www.cliki.net/pattern matching

Прекрасно. Выбираем какую-нибудь реализацию наугад - ну пусть будет cl-match. И видим: «struct prefix &rest field-forms The value must be a structure, and each field must be accessible with a function whose name begins with prefix. Each field form can be either a two-element list, where the first element is the field name and the second element is a pattern, or a symbol (the field's name), which always matches.»

То есть никакого обмена статической информацией не идет, просто реализация НАДЕЕТСЯ, что есть такая структура и у нее будут ацессоры нужного вида (и они обязательно должны начинаться с префикса, ибо не дай бог. то, что ацессоров может даже и не быть в области видимости реализация даже не предполагает). Ну надежда умирает последней, чо. Посмотрим дальше:

(defmac defpattern (patrn args &body body)
  (check-type patrn symbol "DEFPATTERN: 1st arg must a symbol")
  `(eval-always
    (setf (get ',patrn 'cl-match-pattern) #f(lett ,args _ ,@body))))
опять костыль, никакого корректного взаимодействия с областью видимости, будет неожиданно ломаться в случайный местах, использовать нельзя.

О переусложненности и вырвиглазности кода упоминать не стоит - все-таки это CL. Обработки ошибок нету вообще как класса - обычно макрописатели в CL даже за нее не принимаются, т.к., видимо, понимают, что при полном отсутствии соответствующих инструментов это будет титанический труд. Как и ожидалось - it just does not work. Ничего из требований не выполнено, о 50% функционала никакой речи нет - хорошо если 10% соберется.

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

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

Чудесно - оказывается в моем написанном на коленке за 10 минут коде решается неразрешимая задача!

Это в CL этих данных нет - потому что в CL макросистема представляет собой устаревший кусок говна. В нормальных макросистемах все нужные данные есть.

задача компилятора.

Точнее экспандера. Но в общелиспе он эту задачу не решает - гигиены-то нет. По-этому описанная передача статический информации в CL нереализуема.

макросы их синтаксис к языку отношения не имеет. какие захочешь - такие ошибки и выдавай.

Проблема в том, что информации о source location в макросах коммон лиспа нет, а потому нет способа выдать корректные сообщения об ошибках - т.к. там эта информация нужна. В результате использовать в CL макрос, не читая его исходник, и не нзая, во что он раскрывается -невозможно.

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

Я другой анонимус. Просто уточню - в дискуссию я вступать не буду.

В результате использовать в CL макрос, не читая его исходник, и не нзая, во что он раскрывается -невозможно.

Ну это уж точно не так. Я, например, постоянно использую ненавидимый тобой макрос loop и у меня никогда с ним не было проблем. Более того, я никогда даже не заглядывал его содержимое. Модель разработки в CL позволяет обычно всегда весьма легко посмотреть, какой код получается. Тоже самое можно сказать и о других стандартных макросах в CL. Всегда легко и быстро можно увидеть как работает та или иная конструкция, порою даже не читая документацию. В других языках часто бывают подобные проблемы. Насчет ракеты ничего не могу сказать, так как не работал с ней, но меня всегда смущала функциональная направленность схемы, большое количество несовместимых вариаций. Надеюсь, что ракета преодолеет все проблемы схемы.

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

ацессоров может даже и не быть в области видимости

в лисп-1 понятно, что внутри let всё легко сломается. лисп-2 и система сборки решает эти проблемы на практике, а не в воспалённом воображении теоретиков. у меня сложилось мнение, что макросы схемы - это такой lisp++, где путают эффективность и банальную переусложнённость.

реализация даже не предполагает

и не должна. макрос - функция над AST, зависимость от раскрытия от окружения и фаз луны - явно плохая идея.

О переусложненности и вырвиглазности кода упоминать не стоит

обычная обработка списков.

Обработки ошибок нету вообще как класса

даже в четырех строчках, что ты скопипастил одна из них - именно обработка ошибок.

Нет, не приходится. просто берешь и используешь эту любую функцию

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

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

потому что в CL макросистема представляет собой устаревший кусок говна

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

В результате использовать в CL макрос, не читая его исходник, и не нзая, во что он раскрывается -невозможно.

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

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

Есть же либа cl-match, которая, по-моему, как раз и представляет собой ракетовский match http://common-lisp.net/project/cl-match/doc/clmatch.htm

Так я выше написал про нее. Груда костылей, с никаким функционал, да еще и глючная.

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

в лисп-1 понятно, что внутри let всё легко сломается. лисп-2 и система сборки решает эти проблемы на практике, а не в воспалённом воображении теоретиков. у меня сложилось мнение, что макросы схемы - это такой lisp++, где путают эффективность и банальную переусложнённость.

Опять сказки про лисп-2 который решает все проблемы, лол. Да ничего лисп-2 не решает. Более того - он вообще никак не влияет на обсуждаемые аспекты.

и не должна.

Реализация не должна работать? Заебись, лол.

макрос - функция над AST, зависимость от раскрытия от окружения и фаз луны - явно плохая идея.

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

обычная обработка списков.

Именно. Потому и вырвиглазно.

даже в четырех строчках, что ты скопипастил одна из них - именно обработка ошибок.

Одной единственной ошибки. А где остальные обработки остальных? Нету. Это не говоря уже о том, что и та единственная обработанная обработана криво.

что-то ты совсем заврался походу.

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

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

Тем и отличается полноценная макросистема от общелиспового препроцессора, что ничего в этом случае не ломается.

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

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

Ну так на безрыбье и рак - рыба. Так и работает - куча блевотного кода вместо декларативных паттернов, чтение исходников и результата экспанда вместо нормальной отладки. Короче - мыши плакали, кололись, но жрали кактус. Чего ж еще делать? Пустыня, а пить охота.

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

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

Функционально мощнее, т.к. добавляет новые возможности, не отменяя старых (простого defmacro).

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

Именно так, поэтому я часто использую define-macro. _Мне_ так удобно.

И логика там простая - раз практически все символы естественно связывать по месту объявления и лишь некоторые - по месту вызова, то естественно сделать так, чтобы по умолчанию связывание происходило по месту объявления. И мы получаем гигиену.

А мне связывание по месту вызова кажется более естественным, т.к. это концептуально проще. Если вижу, что желательна и уместна гигиена — использую гигиену. Если чувствую, что и defmacro сгодится — не парюсь и использую defmacro. Что плохого в том, чтобы иметь возможность использовать простые инструменты?

Если мне нужно забить гвоздь, то я делаю это молотком, даже осознавая риск попадания молотком по пальцу.

Что вижу в редакторе (S-выражения), то и мешу в макросах.

Надо сказать, что в схемах благодаря паттернам это проявляется лучше :)

Паттерн матчеры, list comprehensions, генераторы визиторов — очень полезные инструменты. Только к гигиене это никакого отношения не имеет. Никто не мешает подобные инструменты использовать в defmacro.

Макросы Схемы же добавляют ещё один уровень сложности

Все совершенно наоборот. Они позволяют не думать о тех вещах, о которых надо думать в гигиенической системе (т.к. обо всем подумает гигиена). Компьютерное время дешевле человеческого. Если задача может быть эффективно решена на компьютере, то зачем ее решать руками? Пусть компьютер и решает. А человеку оставим задачи, которые компьютер решить не в состоянии (благо на всех хватит :)).

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

Проблема просто в том, что первый инструмент вы освоили, а второй - осваивать не хотите.

Почему вы думаете, что не хочу? Зачем мне тогда вообще с вами разговаривать? Чтобы потроллить? Чтобы наставить на путь истинный? :-) Мне действительно очень интересен этот вопрос. Я его _для себя_ хочу решить, из самых эгоистических побуждений.

Пишу дальше...

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

И не потому что он значительно сложнее, а потому что «ну я уже умею делать это при помощи инструмента Х, зачем мне нужен инструмент Y»? Естественно, использовать инструмент, который вы освоили, легче, чем инструмент, который вы не освоили. Но о качестве и реальном удобстве инструмента это ничего не говорит.

Существует большое количество сложных инструментов, которые я не освоил. И есть сложные инструменты, которые я освоил, вложив в их освоение неоправданно много усилий. С опытом я начал лучше понимать, какие подходы и концепции лучше работают конкретно для меня, но понимание это работает почти полностью на интуитивном уровне.

Есть замечательный язык Haskell, делать многие вещи в котором мне неудобно. Поэтому когда мне нужен ML, то я обычно использую гораздо более простой и прямолинейный OCaml, в котором могу легко (пусть, возможно и некрасиво) делать некоторые простые вещи.

«Мужчина!» — говорят мне абстрактные монадические мужики — «Используй трансформаторы монад и все твои проблемы волшебно, в одно мгновенье, покажутся психическим недугом императивщика. Хаскелл вернёт тебе часы, украденные отладкой ошибок — половину жизни обратно получишь ты!».

Но нет вдохновенья и болит голова и рука пишет код некрасивый. И родное, привычное к ML-ю перо не в силах создать музыки IO. Что случилось? — Я глуп? Не способен понять? Не готов к освоенью подхода? А может подход не подходит ко мне; не подходит подхода природа?

«Мужчина, одумайся!» — не унимаются монадисты — «Ты болен, а мы предлагаем тебе пилюлю! Мы сдуем с тебя копоть, прочистим мозги от дыма! Ты расширишь своё сознание сакральным пониманием стрелок и расширений GHC!» — заманивают меня они.

Сознание сопротивляется, но интуиция выносит вердикт — этот инструмент мне не очень хорошо подходит. Меня не тянет к нему и созерцание кода не приводит в восторг. В последнее время я склонен доверять интуиции.

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

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

Я интересовался, проводились ли исследования по сравнению эффективности использования языков программирования, но практически ничего не нашёл. Когда речь заходит про маргинальные языки типа лиспа, то об обширных исследованиях с объективным сравнением каких-нибудь количественных оценок можно и не мечтать.

Да и не совсем понятно, каким образом можно подобные исследования проводить. Слишком большое значение имеют способности программиста. Рядом со мной на работе сидит сумасшедший C++-ник, который висит в топе на TopCoder и похожих сайтах (олимпиадное программирование). Существуют задачи, в которых он меня _на порядок_ уделает по скорости, используя богомерзкие плюсы при кодировании не самых тривиальных вещей (например, он при мне, во время контеста, за час закодил на коленке довольно сложный вариант симплекс-метода (branch and cut, 800 строк на плюсах) и успешно сдал задачу).

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

Я разве что-то говорил про списки? Меня сейчас только вопрос гигиены интересует. Паттерны в схемовских макросах — так, удобный сахарок, который и к defmacro легко прикручивается.

Обход гигиены в классическом макросе, который вводит биндинги, - это _одна_ строчка. Несколько сложнее может быть в случае написания реально сложного макроса, с реализацией эдак на 1kloc (не общелисповых, ясно, в общелиспе это было бы все 10kloc :))

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

Я сейчас попытался написать в Racket игрушечный матчер, умеющий использовать статическую информацию о типах структур. Сразу столкнулся с несколькими моментами, в которых нужно ломать гигиену, и «изящного гигиенического» решения для которых я не придумал (хотя доки долго копал).

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

Сейчас код будет... Только на поддержку пользователей отвлекусь...

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

сидит сумасшедший C++-ник, который висит в топе на TopCoder и похожих сайтах (олимпиадное программирование).

Плюсы решают в алгоритмических задачах, достаточно посмотреть на всякие там рейтинги.

Худо-бедная высокоуровневость, скорость и наличие килотонн готовых структур данных делают свое дело.

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

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

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

Итак, я попытался написать в Racket очень простой макрос match-struct со следующей функциональностью:

; Пусть у нас есть две разных структуры

(struct str1 (a b c))
(struct str2 (c d e))

(define my-str1 (str1 1 2 3))
(define my-str2 (str2 3 4 5))

; Должен вернуть список значений полей переданной структуры
(define (test-match s)
  (match-struct s
    (str1 -> (list a b c))
    (str2 -> (list c d e))))

(test-match my-str1) ; -> (1 2 3)
(test-match my-str2) ; -> (3 4 5)

Понятна идея? match-struct определяет тип структуры и создаёт в нужной ветке биндинги, соответствующие полям этой структуры. Информация о полях определяется статически.

Сначала создаём вспомогательный макрос with-struct, который берёт тип структуры и создаёт биндинги, соответствующие полям (и содержащие значения полей):

(begin-for-syntax

 ; Этот макрос -- простой сахарок для доставания информации о структуре
 ; В синтаксисе используется стрелочка (ну вот нравится мне так)
 ; Мелкий вопрос: как сказать макросу, что это ключевое слово?
 (define-simple-macro (with-struct-info v (it) -> body ...)
   (let ((it (extract-struct-info (syntax-local-value v))))
     body ...))

 ; Получаем имена символов, переданных в syntax-case
 (define-simple-macro (with-symbol-names (in ...) body ...)
   (let ((in (symbol->string (syntax->datum in))) ...)
     body ...))

 ; Генерация имени для биндинга, соответствующего полю
 ; Не придумал, как эту информацию доставать статически. В struct-info её нет
 ; (get-field-symbol struct1 struct1-field1) -> field1
 (define (get-field-symbol basename getter)
   (with-symbol-names (basename getter)
     (let ((rx (regexp (string-append basename "-"))))
       (string->symbol (regexp-replace rx getter "")))))

 ; Генерим пары (имя-поля значение-поля)
 (define (get-fields stx sval getters constructor)
   (datum->syntax stx
     (for/list ((getter (syntax->list getters)))
       `(,(get-field-symbol constructor getter) (,getter ,sval)))))
 )

(define-syntax (with-struct stx)
  (syntax-case stx ()
    ((_ (sval : stype) -> body ...)
     (with-struct-info #'stype (info) ->
       (with-syntax (((_ constructor _ getters _ _) info))
         #`(let (#,@(get-fields stx #'sval #'getters #'constructor))
             body ...))))))

Вот такой простой говномакрос, практически без статических проверок на ошибки (кроме тех, которые Racket бесплатно генерит). В with-struct пришлось грубо сломать гигиену, чтобы ввести новые биндинги. Буду рад, если покажете, как это нужно по-человечески делать. Уверен, что несложно. Дальше сложнее будет.

Этот говномакрос работает:

(with-struct (my-str1 : str1) ->
  (print (list a b c))) ; (1 2 3)

(with-struct (my-str2 : str2) ->
  (print (list c d e))) ; (3 4 5)

Пишем match-struct:

(begin-for-syntax

 ; Генерация имени функции-предиката, соответствующего типу структуры
 ; Не придумал, как эту информацию доставать статически. В struct-info её нет
 ; (get-struct-predicate struct1) -> struct1?
 (define (get-struct-predicate basename)
   (with-symbol-names (basename)
     (string->symbol (string-append basename "?")))))

(define-syntax (match-struct stx)
  (syntax-case stx ()
    ((_ sval (stype -> action ...) . more)
     #`(if (#,(get-struct-predicate #'stype) sval)
           (with-struct (sval : stype) -> action ...) ; Упс
           (match-struct sval . more)))

    ((_ sval) #'#f)))

Упс. Мы в макросе используем другой макрос, который вводит свои биндинги. Мы _не знаем_, что это за биндинги (т.к. сами не заглядываем в стат. информацию), но эти биндинги должны попасть в «action ...». Как в этом случае будем красиво обходить гигиену? Есть какие-то хитрые синтакс трансформеры?

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

Экспромт (прошу воспринимать с юмором):

...ОБЕСПЕЧИТЬ ГИГИЕНУ

ПРИШЛО ВРЕМЯ ОБЕСПЕЧИТЬ ГИГИЕНУ
ГИГИЕНА САМА НЕ ОБЕСПЕЧИТСЯ
ТРАНСФОРМИРУЙ СИНТАКСИС, ТРАНСФОРМИРУЙ ЕГО ЕЩЕ РАЗ
ЗАЧЕМ МНЕ DEFMACRO, У МЕНЯ НЕТ ВРЕМЕНИ ЧТОБЫ ЕБАТЬСЯ С НИМ
ЛУЧШЕ ЕЩЕ РАЗ ОБЕСПЕЧИТЬ ГИГИЕНУ
Я ЗАНИМАЮСЬ ГИГИЕНОЙ ПО 3 РАЗА В ДЕНЬ
КАЖДЫЙ СЕАНС ЗАНИМАЕТ ДВАДЦАТЬ МИНУТ
Я ЖИВУ АКТИВНОЙ И ПОЛНОЦЕННОЙ ЖИЗНЬЮ
Я УСПЕШЕН, ПОЭТОМУ ЦЕЛЫЙ ДЕНЬ ЗАНИМАЮСЬ ГИГИЕНОЙ
А ПОСЛЕ ЭТОГО ПИШУ НА LINUX.ORG.RU
ТУПЫЕ ОБЩЕЛИСПЕРЫ ОДЕРЖИМЫ DEFMACRO
А Я СВОБОДНЫЙ ОТ DEFMACRO ЧЕЛОВЕК
СКАЧАТЬ БЕСПЛАТНО И БЕЗ РЕГИСТРАЦИИ МОКРЫЙ RACKET REFERENCE
КРЯК УЛЬТИМАТ КЕЙГЕН РАЗБЛОКИРУЙ MAYBE
SYNTAX-LOCAL-MAKE-DELTA-INTRODUCER LOCAL-TRANSFORMER-EXPAND/CAPTURE-LIFTS
(DATUM->SYNTAX (SYNTAX->DATUM (DATUM->SYNTAX (SYNTAX->DATUM helper-stx))))
ЛУЧШЕ Я ТРАНСФОРМИРУЮ СИНТАКСИС ЕЩЁ РАЗ
И ЗАБУДУ DEFMACRO, ОШИБКИ МНЕ НЕ НУЖНЫ
Я НЕ ЗАНИМАЛСЯ ГИГИЕНОЙ УЖЕ НЕДЕЛЮ
ПОЙДУ ЗАЙМУСЬ
В SYNTAX-CASE ВСЕ ПРОСТО И ПОНЯТНО
НУЖНО ТРАНСФОРМИРОВАТЬ СИНТАКСИС. ЭТО ЖЕ ОЧЕВИДНО КАК ЭТО РЕШИТЬ
ПРИШЛО ВРЕМЯ ОБЕСПЕЧИТЬ ГИГИЕНУ
КОКОКОКОКОКОКО
(syntax-parse #'1 2) -> readline-input::236: ?: bad syntax in: 2
КОКОКОКОКОКОКО
mrm
()
Ответ на: комментарий от anonymous

В защиту кодволкеров, простой макрос из «Let over Lambda»:

(defmacro with-all-cxrs (&rest forms)
  `(labels
     (,@(mapcar
          (lambda (s)
            `(,s (l)
               (cxr ,(cxr-symbol-to-cxr-list s)
                    l)))
          (remove-duplicates
            (remove-if-not
              #'cxr-symbol-p
              (flatten forms)))))
     ,@forms))

Пример использования:

* (macroexpand
   '(with-all-cxrs
      (cons
        (cadadadr list)
        (caaaaaaaar list))))

(LABELS
  ((CADADADR (L)
     (CXR (1 A 1 D 1 A 1 D 1 A 1 D) L))
   (CAAAAAAAAR (L)
     (CXR (1 A 1 A 1 A 1 A 1 A 1 A 1 A 1 A) L)))
  (CONS
    (CADADADR LIST)
    (CAAAAAAAAR LIST)))
T

Как вы такое без кодволкеров сделаете? Где возьмёте необходимую статическую информацию о функциях, использованных внутри лексического контекста? Нет такой готовой фичи в макросистеме? Будем жаловаться в багтрекер и ждать следующего релиза?

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

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

Это не тролль. Конструктива он уже достаточно привёл, даже программы показал (чего не скажешь о коммонлисперах). Другое дело, что существуют вопросы, природу которых мы пока очень плохо понимаем.

Например, мы пока мало что знаем про то, почему у разных людей отличается «совместимость» с различными подходами и концепциями. Мы не знаем, почему некоторые люди становятся хаскельщиками, некоторые — лисперами, а некоторые молятся на php. Только по историческим причинам (воздействием окружающей среды)? Или же есть прямая связь с типом личности?

Это важные вопросы, они меня давно интересуют.

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

Это важные вопросы, они меня давно интересуют.

Все очень просто: высокоуровневое программирование - гуманитарная дисциплина, сродни математике, лингвистике и писательскому делу, и требует соответственно от программиста наличия литературного вкуса, внезапно да. Чей-то уровень дарьядонцова (пхп), кто-то читается восторженный хайп-треш (руби), другой классицист-натуралист скептик (питон), иной пидарствующий эстет-эссетист (хаскель), лисп выбирают, по моему наблюдению, люди склонные к творческому разнообразию и произвольной компиляции стилей под философским соусом - этакий постмодернизм на метамфитаминах - от депрессивных и развязанных defmacro, до элегантных и эластичных функциональных декомпозиций в шекспировском эмплуа. Perl-поклонники, наверняка, какие-нибудь почитатели творчества Джеймса Джойса, а java-программисты скрытые Маркиза де Сады с его анальной акробатикой и наслаждением от произвольного саздизма.

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

Это важные вопросы, они меня давно интересуют.

Шенк давно всё объяснил. Если вкратце - дело в отношении к дисциплине. Чем больше симпатия к хаосу, тем больше людям нравятся языки типа CL.

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

что в окамле получается проще делать, чем в CL?

Только то, где нужны фичи ML: мощная статическая система типов, ADT, система модулей в стиле SML, pattern-matching, хорошо интегрированный с фичами системы типов. Когда эти фичи не нужны (или сгодятся наколенные хаки), то и OCaml не нужен.

Например, всё это может понадобиться при разработке компиляторов, тем более, что экосистема Окамла к этому распологает (есть готовые компиляторы, системы стат. анализа, куча крутых и проверенных временем библиотек типа CIL, OCamlGraph, биндингов к LLVM, всяческих генераторов парсеров).

Да, можно всё это и поверх лиспа накрутить. Например, в Typed Racket есть все эти фичи и некоторые другие, но работает это не так гладко, как в OCaml: компилятор медленный, сообщения об ошибках плохие, баги попадаются, примеров кода (и готовых проектов) практически нет. Сам дизайн языка ещё практикой не проверен. Хотя штука, мне кажется, перспективная и интересная.

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

OCaml можно прямо сейчас брать и использовать. В реализацию вложено больше 20 лет труда крутых дядек из INRIA. Он работает, как часы. Годный строгий диалект ML. Тупой, как дрова, с предельно простым компилятором и предельно простым рантаймом (с содроганием вспоминаю GHC).

Плюс реализации — маленький, пригодный для встраивания рантайм. Один из моих недавних проектов — компилятор, встроенный в огромную коробочную legacy софтину на Delphi7. Он подрубается к системе в виде обычной виндовой DLL.

Главный, как мне кажется, минус Окамла — отутствие простой в использовании макросистемы. Camlp4 — очень сложный в использовании и крайне плохо документированный инструмент, который по возможностям в подмётки не годится самым тупым лисповским макросам. Для того, чтобы что-то нетривиальное начать делать на Camlp4, нужно как минимум исходники его прочитать (их немного, но это ад из функторов). Обычно использование Camlp4 оправдано только для крупных синтаксических расширений. В остальных случаях это откровенная стрельба из пушки по воробъям. Композабельные макры делать практически невозможно. Макросы, генерящие макросы, практически невозможны (чреваты баттхертом при отладке и усложнением системы сборки).

Собственно, макросистема — единственная фича, которая меня сейчас привлекает в лиспах, манит неудержимо. Если бы её не было — нахер бы мне не сдалось это убогое скобчатое говно. Извиняюсь :-)

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

В typed racket действительно не все так гладко, но он сам молодой и постоянно эволюционирует.

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

Это не тролль.

Это не имеет значения ;)

И, всё-же, подождём его реакции на твои вопросы

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

что в окамле получается проще делать, чем в CL?

Бинарники. Маленькие, быстрые бинарники.

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

В with-struct пришлось грубо сломать гигиену, чтобы ввести новые биндинги. Буду рад, если покажете, как это нужно по-человечески делать.

В общем, обход через datum->syntax - это нормально. Только лучше вешать гигиену именно на те символы, что хотите из под нее вывести и не вешать на скобки - это во-первых, во-вторых, надо понимать, что вы берете контекст у stx.

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

; Генерация имени функции-предиката, соответствующего типу структуры
; Не придумал, как эту информацию доставать статически. В struct-info её нет
; (get-struct-predicate struct1) -> struct1?

Есть. Третий элемент struct-info и есть этот предикат.

Еще момент - если хотите в паттерне стрелочки и двоеточия, то в define-simple-macro надо окружать их ~datum: (~datum ->) например.

Как в этом случае будем красиво обходить гигиену?

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

 (define (get-fields stx sval getters constructor)
   (for/list ((getter (syntax->list getters)))
     #`(#,(syntax-local-introduce (datum->syntax #f (get-field-symbol constructor getter))) (#,getter #,sval))))
Теперь все работает.

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

Например, мы пока мало что знаем про то, почему у разных людей отличается «совместимость» с различными подходами и концепциями.

Да вобщем-то знаем и давно. Банальный сиднром утенка - вы долго использовали дефмакро, этот инструмент стал для вас удобен. Когда вы берете другой инструмент, то пытаетесь использовать его так же как и дефмакро - но внезапно оказывается, что рукоятка неудобна для привычных ударов и бить надо несколько по-другому.

Соответственно, с практикой неудобство пройдет.

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

В защиту кодволкеров, простой макрос из «Let over Lambda»:

И вот возникает вопрос - что будет если у нас некоторый макрос раскрывается в cadadadr? Или cadadadar не стоит в expr-позиции? Или переопределен let'ом? Кодеволкер этого не заметит, нужный биндинг не введет, hur-dur, жопу разорвало. Вообще, да, именно вот такая схема (когда внутри макроса может быть произвольный биндинг, который ВНЕЗАПНО надо как-то раскрыть в зависимости от контекста, при чем конкретное имя неизвестно) вызывает некоторые проблемы. Ну в racket можно выебнуться, переопределив #%app или #%top, что снимет большинство проблем, но не будет работать тогда, когда соответствующий идентификатор уже определен. Еще можно сделать local-expand, оттуда вытащить все идентификаторы нужного вида с нужными связываниями (тем же кодеволкером, но на раскрытом коде), потом сгенерить код-обертку и воткнуть внутрь оригинал - но во-первых у макросов могут быть сайд-эффекты, а экспанд будет производиться несколько раз одних и тех же форм - что нарушит консистентность, а во-вторых при вложении форм друг в друга время экспанда будет расти квадратично с уровнем вложенности. Кроче - глобалнього, надежного решения такой проблемы нет, так что подобных макросов следует избегать.

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

А мне связывание по месту вызова кажется более естественным, т.к. это концептуально проще.

Потому что вы так привыкли :) Концептуально проще связывание по месту определения, т.к. так связываются _функции_. Чем концептуально проще тот факт, что макросы имеют какие-то свои, особенные, правила связывания? :)

Паттерн матчеры, list comprehensions, генераторы визиторов — очень полезные инструменты. Только к гигиене это никакого отношения не имеет. Никто не мешает подобные инструменты использовать в defmacro.

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

Например, отсутствие гигиены могло бы в некоторых случаях значительно усложнить использование того же syntax-parse.

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

Вопрос привычки. Мне наоборот гигиена позволяет не задумываться о корректности макроса - а описывать его логику и it just works. То есть на практике я когда макрос пишу, то не думаю о том, что «ага здесь будет гигиена, а потому этот юзкейс корректен». Я просто знаю, что все будет хорошо и даже не вспоминаю об этих вещах. Уже тот факт, что втыкать генсим надо намного чаще, чем обходить гигиену, говорит о том, что дефмакро ментально дает больший оверхед.

Почему вы думаете, что не хочу?

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

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

Да, можно всё это и поверх лиспа накрутить. Например, в Typed Racket есть все эти фичи и некоторые другие, но работает это не так гладко, как в OCaml: компилятор медленный, сообщения об ошибках плохие, баги попадаются, примеров кода (и готовых проектов) практически нет. Сам дизайн языка ещё практикой не проверен. Хотя штука, мне кажется, перспективная и интересная.

Надо отметить, что Typed Racket существует год-два от силы.

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

Я сейчас попытался написать в Racket игрушечный матчер, умеющий использовать статическую информацию о типах структур. Сразу столкнулся с несколькими моментами, в которых нужно ломать гигиену, и «изящного гигиенического» решения для которых я не придумал (хотя доки долго копал).

Там ее в одном единственном месте надо обходить. И легко обходится. Тут все дело в том, что надо просто знать как работает алгоритм гигиены (или, более конкретно, - как происходит связывание идентификаторов в присутствии гигиены). Тогда вопрос как именно надо обойти гигиену в том или ином месте становится тривиальным. Ну за исключением, наверное, каких-то совсем уж замудренных случаев, которые мне и представить-то сложно. Без обхода гигиены код был бы проще ровно на один вызов syntax-local-introduce и один вызов datum->syntax. Вообще, кстати, можно написать что-нибудь типа такого:

(begin-for-syntax 
  (define-syntax-class unmarked
    (pattern x:expr
             #:with v (syntax-local-introduce #'x))))

(define-simple-macro (test (values ...) body ...)
  #:with (id:unmarked ...) #'(a b c)
  (let ([id.v values] ...) body ...))

(test (1 2 3) (list a b c))
->
'(1 2 3)
то есть соответствующий syntax-class автоматом из-под гигиены выводит. Можно и для datum->syntax аналогичный написать.

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

гуманитарная дисциплина, сродни математике

Настолько тонко, что никто и не заметил. Да в этом итт треде одни анорексики собрались, лол.

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

Гуманитарные науки изучают человека, его поведение, поступки и высеры. Математика сюда не относится.

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

вы долго использовали дефмакро, этот инструмент стал для вас удобен

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

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

И вот возникает вопрос - что будет если у нас некоторый макрос раскрывается в cadadadr?

макрос развернётся в лисп код

Или cadadadar не стоит в expr-позиции? Или переопределен let'ом?

в лисп-2 ничего не будет.

Кодеволкер этого не заметит, нужный биндинг не введет

это не кодволкер, если даже макры раскрыть не может.

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

Гуманитарные науки изучают человека, его поведение, поступки и высеры. Математика сюда не относится.

Математика во-первых - не наука. Во вторых - лингвистическая гуманитарщина, которую мы просто «взяли и придумали» из-за недостатка способа передачи неких абстракций (самими абстракциями она, кстати, тоже занимается весьма в ограниченном режиме - ну, т.е. не является средством их создания, только манипуляции, создает абстракции человеческий разум - таким образом: если научная дисциплина описывает окружающие нас физические процессы, то математика - создает способ описания абстракций, абстрактной информации - придавая ей значение в зависимости от контекста и выдуманных правил интерпретации, математическая эмпирика - это Знание). И поэтому, в частности, математика выступает предметом ее (лингвистики) изучения. Зачем-то лингвистику математического языка скрестили с ужом^W философией и ежом^W логикой (другой гуманитарной дисциплиной - разделом хуйпоймичег^W то ли математики, то ли философии) - и назвали метаматематикой. Чем эта мемаматематика отличается от обычной беседы математиков на философские темы в LSD-трипе, тоже сходу не поймешь. А так, достаточно весело читать, как программистов называют «технарями», когда все базовые дисциплины (даже не науки) у них гуманитарные: математика, лингвистика, логика (а корни логики в этике) и философия.

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