>Вопрос: она поддерживает уровни трассировки и сложные команды (подпрограммы)?
Пардоньте, что именно означает "уровни трассировки"? И нафи^W для чего это нужно на практике?
А "сложные команды (подпрограммы)", если я правильно это понимаю, поддерживаются. Т.е. клиент может отправить сразу N различных команд и сервер выполнит их последовательно. Собственно, так робот и работает.
> Пардоньте, что именно означает "уровни трассировки"?
Различные уровни детализации вывода.
> И нафи^W для чего это нужно на практике?
> Т.е. клиент может отправить сразу N различных команд и сервер выполнит их последовательно. Собственно, так робот и работает.
Клиент может работать, как минимум, двумя разными способами. Один способ -- это когда он отправляет сразу всю серию команд на сервер, а после отработки показывается только результат работы. Другой способ -- это когда робот отправляет на сервер команду за командой, и после каждой команды показывать состояние мира. В моем варианте на Лиспе это записывается двумя разными способами, например:
((go-west go-west go-west))
и
((go-west) (go-west) (go-west))
Вот те куски, что внутри -- это подпрограммы. А уровень трассировки задает, когда будет выводиться состояние мира. Например, если УТ равен 0, то только в конце программы, если УТ равен 1, то в конце каждой подпрограммы первого уровня и т. д.
Для робота может быть полезно записать три уровня вложенности -- для всей программы целиком, для демонстрации в точках подъема предметов и после каждого шага. Соответственно, можно задать три уровня трассировки. Правда, сейчас у меня робот всегда формирует программу только для самого детального уровня, как это требуется в условии, хотя сначала он у меня работал на нулевом уровне. Это, кстати, усложнило программу.
Еще, может быть, есть смысл ввести команду show-world, чтобы задавать явно точки отображения мира. И заодно разрешить использовать в программе метакоманду autocollect, которая разворачивается в соответствующую подпрограмму. А отсюда уже один шаг к именованным подпрограммам. Метакоманду quit можно дополнить метакомандами return, которая выходит из текущей подпрограммы, и exit, которая завершает выполнение подпрограмм и выходит на заданный уровень вложенности или вообще завершает выполнение. Добавьте сюда условное исполнение и цикл, и получите уже достаточно мощный DSL управления роботом, типа Лого или Lua.
> Раскрыть в объявлении констант pairlis - помимо экономии слова, > имхо, нагляднее
Я пробовал, но оно у меня ругнулось, когда я попробовал применить к такому списку assoc. Я думал, ассоциативные списки делаются только специальными функциями. Дома проверю.
> (defconstant +directions+ ..
А в чем сакральный смысл плюсов в дефиниции? Если это соглашение по именам констант, то почему command-reversion сделано без них? И я еще видел переменные, окаймленные астериксами -- *blah* -- что это значит? И вообще, есть ли соглашения по кодированию и стилю программ на Лиспе и где об этом можно почитать?
> 3. Мелкие исправления
Понятно, для меня это вообще проблема -- отличить место, где есть неявный progn. Очень часто пытаюсь применить его в теле функции, кажется, так нельзя? По крайней мере, было несколько странных эффектов, с тех пор стараюсь, когда сомневаюсь, указывать progn явно или вообще пользоваться cond. Про (if (null x) () ...) -- хотел показать, что основой рекурсии является пустой список.
> Многострочные setf
Просто не знал :-). Получается, что для атомарных имен setf ничем не отличается от setq, но позволяет писать несколько присваиваний? Почему такой возможности нет у setq?
> 5. От одного eval можно легко избавиться (но это как раз увеличивает код
Каюсь, именно в этом месте погнался за оптимизацией.
> +(def-commands #.+directions+)
Что делает #.? Насколько я знаю, хэш означает блокировку, для чего она в этом случае?
Кстати, тут пару десятков страниц назад затрагивали тему рефакторинга. Как раз споткнулся об это дело в Лиспе. Сначала программа использовала глобальные переменные, а затем появилась структура. Пришлось везде заменять на обращения к атрибутам. Теперь предстоит заменить обращения к атрибутам на вызов методов.
Вторая задача -- переименование. Суть в том, что после компиляции лисп-программа уже является некоторым связаным деревом. Было бы интересно поиметь некую волшебную функцию (defun rename (funname)), которая заменяла бы имя функции в дереве, а потом декомпилировать в исходный код. Кстати, для Лиспа есть декомпиляторы?
Я так подумал, что часть задач рефакторинга можно решать на самом Лиспе, потому как программы на нем им же и могут обрабатываться. Но тут вся загвоздка в pattern-matching, например, должна быть некая функция like, которая бы выдавала истину для такого, например, выражения:
(like '((a b) c) '(d e))
то есть, выполняла бы поиск гомоморфизмов на деревьях. А если бы к этому еще работал и биндинг а-ля Пролог (то есть, после выполнения символ d содержал список (a b)), то это была бы вообще прелесть. Может быть, это equalp делает? Я просто еще не разобрался в его семантике.
В общем, есть что-нибудь пользительное для анализа кода на Лиспе?
>Клиент может работать, как минимум, двумя разными способами. Один способ -- это когда он отправляет сразу всю серию команд на сервер, а после отработки показывается только результат работы. Другой способ - это когда робот отправляет на сервер команду за командой, и после каждой команды показывать состояние мира. В моем варианте на Лиспе это записывается двумя разными способами.
А... это... и всего-то, конечно можно. Давайте вспомним постановку задачи, там чётко задана команда сервера "world", которая присылает текущее состояние мира. Так вот, мой сервер и клиент не делают лишних (ненужных) телодвижений, а просто используют установленный протокол. Короче, чтобы обеспечить "максимальный уровень трассировки" клиент после каждой команды движения посылает команду "world", причём не для себя, а для человека за монитором, чтобы ему удобно рассматривать было. Вот так сейчас и сделано. Если убрать эти "лишние" world -- моя программа станет на пару слов короче.
В общем, у меня сам клиент решает, когда показать состояние мира человеку. Например, тривиальным образом (одно слово переместить) я могу сделать отображение мира только в момент подъёма/опускания. Могу показывать мир только по четвергам ночью в полнолуние ;)
А вот на счёт последнего Вашего абзаца... Вы уж меня извините, но какая-то белиберда бесполезная... Сплошные лишние сущности. Это всё реализуется проще, даже не выходя за рамки стандартного протокола.
под последним параграфом я имел в виду вот этот текст:
>Еще, может быть, есть смысл ввести команду show-world, чтобы задавать явно точки отображения мира. И заодно разрешить использовать в программе метакоманду autocollect, которая разворачивается в соответствующую подпрограмму. А отсюда уже один шаг к именованным подпрограммам. Метакоманду quit можно дополнить метакомандами return, которая выходит из текущей подпрограммы, и exit, которая завершает выполнение подпрограмм и выходит на заданный уровень вложенности или вообще завершает выполнение. Добавьте сюда условное исполнение и цикл, и получите уже достаточно мощный DSL управления роботом, типа Лого или Lua.
> Потом опять же что-то вроде CELLS никак не сделать.
Мы сейчас как раз пытаемся использовать некую rule-based систему. Причем, так как наши программисты -- самые программисты в мире, то сей велосипед был написан нами полностью с нуля в три прыжка. Каюсь, я к этому тоже руку приложил.
Когда зашла речь о CELLS, мои архаровцы тоже стали искать что-то похожее и таки нашли RETE для Oracle и еще какую-то поделку для .Net. Но менять технологию, похоже, уже поздно...
> Давайте вспомним постановку задачи, там чётко задана команда сервера "world", которая присылает текущее состояние мира.
Давайте вспомним, с чего вообще начался спор. Было указано, что Лисп начинает показывать свои преимущества только на достаточно крупных задачах, потому как на программах класса "Hello, world" он даже хуже, чем другие быд^Wязыки.
> Так вот, мой сервер и клиент не делают лишних (ненужных) телодвижений, а просто используют установленный протокол.
Увы, в реальном мире системам свойственно эволюционировать, и даже аппеляция к согласованному и подписанному техническому заданию при спорах с заказчиком не всегда спасает. Речь идет о том, что на Лиспе проще писать программы, способные эволюционировать в соответствии с усложнением требований предметной области. Опять же, задача была выбрана, чтобы показать преимущества развивающегося DSL. По-моему, это было отлично продемонстрировано.
Открою по секрету, что небольшое изменение лисп-программы позволит роботу исполнить удаленно _любую_ лисп-программу, в том числе с ветвлениями и циклами. То есть, простота DSL тут вяжется с встроенной мощью Лиспа, о чем тоже говорили вначале.
Я бы даже сказал так, что многие фичи лисп-программ очень часто получаются исключительно как "побочный продукт" решения основной задачи. То есть, вроде бы и не собирался наделять программу этим свойством, и вдруг обнаруживаешь, что она и так может. Кайфовое ощущение :-). Нужно просто немножко отойти от парадигмы программирования "под заказ" :-).
> клиент после каждой команды движения посылает команду "world", причём не для себя, а для человека за монитором, чтобы ему удобно рассматривать было.
Вот лично мне, как человеку, было жутко неудобно смотреть на гору мусора, который выдает робот при своей работе. Достаточно было бы посмотреть только начало и конец операции, а также несколько контрольных точек, в основном, на поворотах. Я не утверждаю, что есть только два способа -- мой и неправильный. Я утверждаю, что в реальных задачах зачастую нужен гибкий подход и кустомизация решения под конкретного пользователя.
> В общем, у меня сам клиент решает, когда показать состояние мира человеку.
Когда компьютер начинает принимать решения за человека, то получается техноужыс вроде терминаторов, матриц и прочих оффтопиков XP ;-). Лично я люблю сам определять уровень получаемой информации.
> Могу показывать мир только по четвергам ночью в полнолуние ;)
Важно, чтобы это умел пользователь, которому Вы предлагаете свое творение.
> А вот на счёт последнего Вашего абзаца... Вы уж меня извините, но какая-то белиберда бесполезная... Сплошные лишние сущности.
Хум хау. Кому и станки с ЧПУ -- это сплошные лишние сучности. Однако в жизни обычно чаще бывает наоборот...
> Это всё реализуется проще, даже не выходя за рамки стандартного протокола.
Никто не спорит, что любую задачу можно решить, вопрос только времени и денег. Однако даже в этом случае лисп-программа в некоторых аспектах уже реализовала больший функционал (речь идет конкретно о возможностях DSL).
debugger invoked on a SB-INT:EXTENSION-FAILURE: Don't know how to REQUIRE comm. See also: The SBCL Manual, Variable *MODULE-PROVIDER-FUNCTIONS* The SBCL Manual, Function REQUIRE
Type HELP for debugger help, or (SB-EXT:QUIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name): 0: [ABORT] Exit debugger, returning to top level.
(SB-IMPL::REQUIRE-ERROR "Don't know how to ~S ~A.") 0]
Где взять, я не посмотрел, а настроить просто. В sbcl -- исходник, в .sbcl/systems -- ln -s на .asd. Для sbcl этот линк -- доступность пакета. Тогда require видит его без всяких вопросов.
Еслиты тестируешь программы на разных лиспах, и если лисп поддерживается common lisp controller, то лучше положить все программы в каталог, скажем, ~/cl, создать ~/.clc/systems и по аналогии с sbcl наделать линков на *.asd. Тогда исходники увидит много лиспов.
> В sbcl -- исходник, в .sbcl/systems -- ln -s на .asd.
Ну, это мы уже проходили. Вопрос в том, на что именно линк. Я такого пакета вообще не нашел.
> Если ты тестируешь программы на разных лиспах, и если лисп поддерживается common lisp controller
Тут бы один освоить...
Есть просто такое подозрение, что самое вкусное (а именно, организация сетевого взаимодействия) именно в этом пакете. Если он самописный, то это фол: нельзя прятать сложность программы в самописной библиотеке (хотя я не уверен, что это не так у нынешнего лидера). Если это стандартный модуль, то хотелось бы посмотреть -- может мне стоит на него перейти.
>Ну, это мы уже проходили. Вопрос в том, на что именно линк. Я такого пакета вообще не нашел.
И не найдешь. Человек явно писал программу на LW. Чтобы было универсально, то для открытия сокетов, чтения-записи и пр. делают враппер, а потом условной компиляцией подставляют нужные функции.
> Есть несколько предложений, но пока "чисто косметических" - никаких
> изменений в алгоритме.
Все принял, но все никак не пойму, что делает #. В стандарте сказано,
что это read-time evaluation (я правильно понял?), но я не пойму, когда
это на самом деле вычисляется.
В любом случае, это все еще косметика:
Total length 1745
Meaning length 545
Total thesaurus 211
Meaning thesaurus 125
Total saturation (%) 31
Thesaurus saturation (%) 59
Total expressiveness (%) 12
Meaning expressiveness (%) 23
> Для sbcl и cmucl надо использовать (require :sb-bsd-sockets). Но там
> уже функции другие.
* (asdf:operate 'asdf:load-op 'trivial-sockets)
; loading system definition from
; /usr/share/common-lisp/systems/trivial-sockets.asd into #<PACKAGE "ASDF0">
; registering #<SYSTEM TRIVIAL-SOCKETS {10027B7691}> as TRIVIAL-SOCKETS
; loading system definition from
; /usr/lib64/sbcl/sb-bsd-sockets/sb-bsd-sockets.asd into #<PACKAGE "ASDF0">
; registering #<SYSTEM SB-BSD-SOCKETS {1002A67B11}> as SB-BSD-SOCKETS
Похоже, я именно их и использую. Точнее, обертку в виде trivial-sockets.
Говорят, есть еще более высокая обертка, но не для SBCL/CMUCL.
> Ну вот, новая версия на OCaml, сократил немного за счет логики и за > счет ввода/вывода. Теперь получается 114 непробельных (порой довольно > длинных) строк.
Total length 1396 Meaning length 461 Total thesaurus 159 Meaning thesaurus 106 Total saturation (%) 33 Thesaurus saturation (%) 67 Total expressiveness (%) 11 Meaning expressiveness (%) 23
Total length 1396
Meaning length 461
Total thesaurus 159
Meaning thesaurus 106
Total saturation (%) 33
Thesaurus saturation (%) 67
Total expressiveness (%) 11
Meaning expressiveness (%) 23
> Человек явно писал программу на LW.
Тады ой. Статистика явно хорошая:
Total length 325
Meaning length 120
Total thesaurus 105
Meaning thesaurus 72
Total saturation (%) 37
Thesaurus saturation (%) 69
Total expressiveness (%) 32
Meaning expressiveness (%) 60
Однако по оценкам волновой алгоритм может довести длину примерно до 900. Это тоже хорошо, но где гарантия, что это работоспособно?
Так Вы скажите, что сделать-то нужно, а? Вы уж определитесь с задачей. А то делаем одно, потом небыдло-лисп зилот сплоховал, ищет оправдания, а виноваты, понятно, быдлоязыки и узколобые людишки.
Да успокойтесь Вы :-). Можете считать что на отдельно стоящей учебно-тренировочной задаче пока что Питон с Окамлем сделали Лисп :-).
> Вы уж определитесь с задачей. А то делаем одно, потом небыдло-лисп зилот сплоховал, ищет оправдания, а виноваты, понятно, быдлоязыки и узколобые людишки.
Зря кипятитесь. В жизни оно так и бывает чаще всего: заказчик сам не знает, чего хочет, и только после пилота к нему внезапно приходит озарение, как нужно было сделать. Как пишется в одной умной книжке, "сначала проектируют как сарай, потом делают сарай, а внедряют уже как небоскреб". Щас тянем уже три таких "быдлопроекта" и на горизонте еще три отчетливо прописываются. А шо поделать -- это жизнь :-).
Насчет "небыдло-лисп", так я даже не "зилот", я вообще "неофит". Для меня ведь этот спор не способ вьюношеского самоутверждения, а попытка обтрусить незнакомый язык в экстремальных ситуациях с целью ознакомления. Ибо ни финны ни sicp со своей детсадовской манерой изложения такого опыта не дают.
Вот и получается, что лично для себя я вынес понимание того, что такое DSL и как макросы могут существенно сократить код (в одном случае) и повысить функциональность (в другом). Вы, как я понял, вынесли понимание того, что Лисп сосет. Ну это уже suum quique :-).
Наконец, позволю себе заметить, что переход на личности слегка не красит оппонента. Вполне вероятно, что у Вас есть опыт написания сетевых приложений, который Вы успешно применили. Понятно, что я в этом вопросе сосунок по сравнению с Вами. С другой стороны, если бы взяли более близкую мне задачу синтаксического/лексического анализа, то все могло сложиться совсем по другому. Ведь аналог моей мерялки на Питоне я пока что не видел ;-).
Все это, как говорится, не флейма ради, а справедливости для...
> Для меня ведь этот спор не способ вьюношеского самоутверждения, а попытка обтрусить незнакомый язык в экстремальных ситуациях с целью ознакомления.
Кстати, я только сейчас обратил внимание, что я для экстрима еще и экзотические структуры данных выбрал. Если в субботу пробьет, попробую портануть Ваш алгоритм на более классических структурах. Не боитесь, что программка на Лиспе и покороче может стать? ;-)
>(require "comm") >debugger invoked on a SB-INT:EXTENSION-FAILURE: Don't know how to >REQUIRE comm. See also: The SBCL Manual, Variable *MODULE-PROVIDER->FUNCTIONS* The SBCL Manual, Function REQUIRE
К сожалению я использую исключительно под Lispworks, модуль COMM под SBCL в том же виде не существует, там надо использовать trivial-scokets или usockets (последняя еще разрабытывается). Встроенная библиотека сокетов SBCL IMHO малость низкоуровневая. Не думаю, что возникнут какие-то проблемы с портированием сокетного кода на SBCL.
Код под Lispworks тем не менее является портабельным (в пределах Lispworks) и должен без изменений работать на WIN32,Linux,FreeBSD,MAC OS и UNIX (???), и скорее всего пойдет на 64 битной версии (Lispworks 5.0).
>Однако по оценкам волновой алгоритм может довести длину примерно до >900. Это тоже хорошо, но где гарантия, что это работоспособно?
Нет пока гарантий, я его не пробовал запускать еще. С работой небольшой завал. Может к вечеру клиента портану. Свою версию соорудить вообще некогда было. Поэтому я и написал что мол "предварительная версия". Вообще питоновский код хорошо пошел портироваться после введения некоторых доп. макров, волновой алгоритм не должен много отъесть, там еще функция считывания мира будет для клиента и для сервера повторно использоваться.
>В общем, есть что-нибудь пользительное для анализа кода на Лиспе?
Как минимум есть множество разношерстных codewalkers, теоретически их одних достаточно, чтобы заниматься переименованием и т.п. О рефакторинге на Лиспе вообще мало что слышно, то ли каждая контора тайком свой велосипед изобретает, то ли он вообще не нужен, не понятно.
>Можете считать что на отдельно стоящей учебно-тренировочной задаче >пока что Питон с Окамлем сделали Лисп :-).
OCaml скорей всего будет выполняться шустрее, но Питон в императивном стиле более краток. Лисп с оптимизациями наверняка приблизится к OCaml по всем параметрам.
> Было указано, что Лисп начинает показывать свои преимущества только на достаточно крупных задачах, потому как на программах класса "Hello, world" он даже хуже, чем другие быд^Wязыки.
Однако, никто это реальным опытом подтвердить не может. Ну кроме viaweb.com естественно (хотя есть и контрпример: reddit.com). Я тут спрашивал про реальные проекты на Лиспе, ни у кого не было крупных проектов на лиспе.
Т.е. преимущества лиспа проявляются только на крупных проектах, которых не существует :-)
> Да успокойтесь Вы :-). Можете считать что на отдельно стоящей учебно-тренировочной задаче пока что Питон с Окамлем сделали Лисп :-).
У меня есть предложение: пусть модераторы всем участникам контеста добавят по звезде за заслуги :-)
Порешим на том что победила дружба :-) И лисперы прекратят вопли про быдлоязыки, по типу этого:
Ибо воистину. Первый Язык, жемчужина посреди простых камней, и нет языков кроме Него. Скобки, в которых пустота - тело Его, мистическое двуединство кода и данных - дух Его, божественная рекурсия - сердце Его. Истинно говорю вам, избегающий света Его есть безумец, вот, свершается кара над главой его, и убогостью отмечены поделия его, подобные пустым глиняным горшкам рядом с хрустальным сосудом благодати Его. Принявший же и постигший истинный свет Его подобен прямой и отточенной стреле, чисты помыслы его и крепка рука его, и благословенны творения его, дарующие радость и утоляющие печали, ибо одухотворены духом Его и отмечены благодатью Его.
(это на lorquotes посылать не надо, это уже оттуда)
> Ведь аналог моей мерялки на Питоне я пока что не видел ;-).
Ну лично я вообще в синтаксическом анализе/разборе вообще ни в зуб копытом. Это узкоспецифическая задача.
Добавлена возможность выполнения нескольких комманд за раз и комманда "autocollect". Человеческий клент имеет дружетвенный интерфейс, при заменяет сокращения типа "e e e n p s d" на "east east east north pickup south drop". При проигрывании промежуточных состояний мира между разными состояниями мира вставляется задержка.
Особо не старался писать компактно, т.к. все представленные на контест программы имеют разный функционал и в прямую их сравнивать, несколько не корректно.
В программе интересно реализована комманда "autocollect": В классе World в методе action_autocollect(), создаётся сервер-заглушка привязанный собственно к этому экземпляру мира и робот, привязанный к этому серверу. Робот умеет прокладывать путь через лабиринт, и вот этот робот и используется для хождения по лабиринту
Будем добавлять новые фичи, ну там монстров, NPC, прокачку персонажа?
Во-первых, мне 27 лет, и намёки на юношеское-там-что-то идут в сад вместе со своим отправителем.
Во-вторых, на личности переходите именно Вы, поскольку аргументов у Вас в виде красивого кода, как я вижу, нет.
В третьих, не нужно мне приписывать, что я там вынес и т.д. Лучше занимайтесь программированием.
И в четвёртых, про "не боитесь и т.д.": не боюсь. Мне Вашего кода боятся нечего :) Вы из тех людей, что любят всех учить и теоретизировать, как нужно делать, а как до дела доходит... начинаются гнилые отмазки, мол, это жизнь, заказчики, небо голубое, и т.д. Ведите себя по-мужски, умейте проигрывать молча.
Теперь я расскажу, что я вынес из всего этого. Лисп мне как раз интересен, но Ваше исполнение действительно сосёт (перейду на Ваши термины), и несколько раздражает, когджа Вы ещё после этого учите меня программировать и открываете тайны жизни. Вот некий ананимус классно портировал adv_server.py, мне очень понравилось, сразу видна красота лиспа.
P.S. Далее буду только читать (может быть), поскольку уже не интересно стало.
> Порешим на том что победила дружба :-) И лисперы прекратят вопли про быдлоязыки, по типу этого:
> Ибо воистину. Первый Язык, жемчужина посреди простых камней...
Вообще-то, я не лиспер. ;) Язык Лисп замечателен тем, что раз и навсегда меняет взгляд на вещи и расширяет сознание. И я всерьёз думаю, что любой приличный программист ну просто обязан с ним познакомиться, хотя бы в объёме SICP (и прорешать все задачи оттуда, как тут советовали). Иначе он будет всю жизнь заново изобретать Лисп, не подозревая об этом (с). А вот для реальных проектов современные лиспы имхо мало подходят. И несмотря на всю свою идеальность и универсальность всё равно сливают более специализированным и прагматичным "быдлоязыкам", как только дело доходит до реальных проектов.
Ну то, что OCaml будет выполнять быстрее, это понятно, а вот за то, что
бы показать, что он самый краткий я и не стал бы бороться. Все таки
нет там синтаксического сахара python'а и lisp'а, да и стандартная
библиотека мягко говоря меньше.
to realsmart:
Что-то ты слишком вскипел. Если бы ты был внимателен, то заметил бы, что
вначале eugine_kosenko также относился к lisp скептически, но в отличие
от других попробовал и сделал выводы (свои, а не насаждаемые ему из
вне). Более того свои выводы он тебе не насаждает и не проповедует - он
их просто высказал. И разговаривает вполне в спокойной манере. Я не
понимаю, что ты так вскипел? В посте от 27.10.2006 1:14:47 единственное,
что могло вам не понравится, так это высказывание про юношеское
самоутверждение, так я его могу отнести также и на свой счет, но
почему-то я спокоен. Будьте спокойней и вы, я думал, что как раз сейчас
сложилась вполне дружественная атмосфера, а вы ее зачем-то нарушаете...
Вообще-то наша маленькая задача и даже мегаанализ eugine_kosenko ничего
не доказывают и не показывают, неужели ты этого не понимал с самого
начала? Я лично взялся просто из спортивного интереса.
realsmart, вы не подумайте, я действительно не имею против вас ничего...
Но перечитайте топик, там было что-то вроде от eugine_kosenko: "лисперы
пока молчат, поэтому я вот тут попробовал себя в лиспе и получилось так".
А лисперы действительно почему-то молчат. И разговор перешел вполне в
цивилизованное русло, давайте его также и продолжим. А по поводу
фанатизма, когда-то слышал примерно следующее: "на любую хорошую идею
всегда найдется неприятность в виде слишком ярых последователей".
P.S. Лисп действительно очень хороший язык. Просто разговоры про
улучшение на порядки - это чистый фанатизм. Современные языки (python,
ruby) очень сильно приблизились к нему по возможностям (я не спорю, что
достигнуть лиспа им не удастся (хотя бы в метапрограммировании из-за
лиспового синтаксиса)), поэтому лисп не дает такого преимущества, как
давал когда-то по сравнению с фортраном и C.
>И несмотря на всю свою идеальность и универсальность всё равно >сливают более специализированным и прагматичным "быдлоязыкам", как >только дело доходит до реальных проектов.
>Т.е. преимущества лиспа проявляются только на крупных проектах, которых не существует :-)
Нет, ну тут были какие-то ссылки. И я приводил ссылку на проект Prism. Вот как раз есть у них статейка по поводу применения Common Lisp в системе. Приведены свои аргументы по поводу, почему именно CL. Четыре странички, кажется. Можно ознакомиться здесь:
А крупные проекты были. В период, когда продавались дорогие LISP-машины, их было навалом. Но только это у тех, кто эти машины покупал. Т. е. внутри больших компаний и организаций. Надежды увидеть это все на столах в виде редактора Paint или MS Word (гы-гы) нет (пока).
Не на пустом месте, а на собственном опыте. :) И я считаю, что:
1. S-выражения труднее читать и понимать, чем код на том же Питоне. Во всяком случае, подавляющему большинству людей. :)
2. До сих пор нет нормальных свободных реализаций Лиспа, пригодных для моих задач.
На предыдущей работе я возился с числодробильным софтом на фортране и C++. Пытался использовать Lush, но оказалось, что он не даёт особенных преимуществ. То есть, те куски кода, где нужна производительность, приходится переписывать в стиле C. Или просто переписывать на чистом C. В конце концов, оказалось, что проще все узкие места писать на С(++) или быдлофортране, а остальное делать на Питоне. Сейчас я занимаюсь гуями на (Py)Qt, и здесь Лисп отпадает хотя бы по той причине, что нет лисповских привязок для Qt. :) А для метапрограммирования в этих задачах и Питоновских замыканий и метаклассов хватает с лихвой. Ещё возился одно время с обработкой текстов. Довольно естественным казалось писать всё это на Лиспе, потом с Лиспа я плавно перешёл на OCaml, потому что его статическая типизация в таких задачах рулит. А с него - на Питон, правда, не по доброй воле, а потому, что начальство приказало. :) Особого выигрыша по сравнению с Камлом Питон не дал, но по крайней мере, для него больше библиотек и больше программистов. :) (Как побочный проект тогда появился http://pybtex.sourceforge.net/).
Хотя, если вы приведёте мне пример реального проекта, где Лисп объективно заруливает всех остальных, буду благодарен. :)
> Если это соглашение по именам констант, то почему command-reversion сделано без них?
Забыл :(
> И я еще видел переменные, окаймленные астериксами -- *blah* -- что это значит? И вообще, есть ли соглашения по кодированию и стилю программ на Лиспе и где об этом можно почитать?
> Понятно, для меня это вообще проблема -- отличить место, где есть неявный progn. Очень часто пытаюсь применить его в теле функции, кажется, так нельзя?
Можно, но необязательно :) Т.е. он там просто лишний
> По крайней мере, было несколько странных эффектов, с тех пор стараюсь, когда сомневаюсь, указывать progn явно или вообще пользоваться cond.
CLtL явно говорит, что нужно - form или forms :)
> Про (if (null x) () ...) -- хотел показать, что основой рекурсии является пустой список.
Лучше уж комментарии писать (хотя по мере того, как код становится всё проще и легче читать - очень трудно заставить себя это делать)
> Просто не знал :-). Получается, что для атомарных имен setf ничем не отличается от setq, но позволяет писать несколько присваиваний? Почему такой возможности нет у setq?
Есть и у setq. А setf для атомарных имён именно setq и использует (как правило - зависит от реализации, но результат в любом случае тот-же). Посему просто срабатывает привычка setq не использовать :)
P.S. А по малеёшим подозрениям лучше лезть в CLtL/HyperSpec :)
> Что делает #.? Насколько я знаю, хэш означает блокировку, для чего она в этом случае?
Ну, ты уже всё нашёл :) Да, read-time evaluation. Т.е. форма за #. вычесляется именно сразу после прочтения. Это позволяет в макру передать именно список, а не имя перемнной, его содержащей. Но нам это позволяет ещё сделать то, что defconstant выполняется в момент компиляции. С обычной переменной так не получится, если только не засунуть код в (eval-when...)