LINUX.ORG.RU

[Lisp] туплю с defmacro

 


0

2

Есть код:


(defun get-action-name (list)
	(mapcar #'(lambda (def-list) (list (first def-list) (second def-list))) list))

(defmacro with-new-actions (parent actions-list
							&body body)
  (get-action-name actions-list))

(defparameter *workspace-actions-list* 
  '((aNew "&New" #'new-page-handler "tab- new" "Ctrl+N")
	(aOpen "&Open" #'open-page-handler "open" "Ctrl+O")))

(with-new-actions 'parent *workspace-actions-list*) ;; 1

(with-new-actions 'parent ((aNew "&New" #'new-page-handler "tab- new" "Ctrl+N")
	(aOpen "&Open" #'open-page-handler "open" "Ctrl+O"))) ;; 2

Проблема в том что строка (2) раскрывается, а строка (1) - нет.

Вопрос как раскрыть *workspace-actions-list* внутри defmacro ? Google молчит, вот туплю и мучаюсь.

★★★
Ответ на: комментарий от den73

> В общем, без явного управления памятью предельная

производительность недостижима.


Очень спорно, потому что за malloc тоже надо платить.

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

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

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

> Хотя, если подумать, может понадобиться несколько образов.

Лично я вообще образы не использую, с ними столько мороки...

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

> Очень спорно, потому что за malloc тоже надо платить.
Например, можно держать пулы свободных кусков памяти разного размера, реализованные в виде двусвязных списков. В этом случае, пока пулов хватает, выделение и освобождение памяти происходит за константное (малое) время, а до malloc вообще дело не доходит. Подобным образом устроен менеджер памяти в Дельфи, да, думаю, и не только в нём.

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

Не, тут своих проблем хватает. Для специальных случаях пулы ресурсов можно и в CL держать. Просто вопрос о том что быстрее в предельном случае это проблема для диссертации, а не обсуждения на ЛОРе ))

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

> вопрос тем, у кого при переопределении макроса его call sites ломаются. А чего бы не повесить хук на такой рестарт?

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

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

то есть, при конпеляции переопределения происходит \

(setf (symbol-function 'foo)
       (compile nil '(lambda () "replaced"))) =>  #<Compiled-Function>

этот symbol-function по идее и есть откомпилированный код.

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

> Не, тут своих проблем хватает.
Каких?

Для специальных случаях пулы ресурсов можно и в CL держать.

Но в стандарте нельзя заставить append брать консы из этого пула и здесь лисп сливает против C и Delphi, где можно задать свой менеджер памяти.

Для специальных случаях пулы ресурсов можно и в CL держать.

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

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

а если над compile накрутить compiler-macro, который будет его затенять и вызывать real-compile, работать будет?
а уже этот compiler-macro с именем compile и будет граф зависимостей собирать.
а то зачем нам в руки такой золотой молоток ^W^W^W такая возможность переопределять символы из стандартных пакетов? :))

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

Т.е., я знаю способ узнать имя текущей компилируемой функции, но надо переопределить defun и ещё кучу def... Что-нибудь может сломаться при взаимодействии с другими библиотеками, которые тоже могут переопределять эти системные def..., но по-своему, и не рассчитывать на наш хук. В общем, сделать можно, но будет хрупко. Проще помещать макросы в правильное место и пользоваться местным аналогом make (благо, его вроде починили) для перезагрузки зависимого кода на уровне файлов. У меня например, повелось делать в системах вторым после package.lisp файл vars-and-macros.lisp

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

> а то зачем нам в руки такой золотой молоток ^W^W^W такая

возможность переопределять символы из стандартных пакетов? :))


Вообще-то, стандартные пакеты залочены, просто так ничего не переопределишь. Разлочить можно, но возможность такая нужна для разработчиков реализации, а не для прикладных программистов. В реализациях, подобных SBCL, т.е. написанных на самом CL провести чёткую грань между разработчиками реализации и прикладными разработчиками несколько затруднительно, да и совершенно не нужно, ибо «что хорошо для разработчиков языка, то хорошо и для его пользователей» (с) (как-то было сказано в PCL).

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

Если проблема в функции, то ведь просто будет показано её имя на стандартном выводе? В смысле, что они там все показываются по очереди ведь, на чём остановились - там и ошибка. А asdf сейчас делает рестарт, где показывает путь к файлу, в котором произошла ошибка (раньше вроде его не было).

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

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

> Если проблема в функции, то ведь просто будет показано её имя на стандартном выводе?
Речь шла о запоминании графа зависимостей функций от макросов, чтобы можно было при изменении макроса автоматически перекомпилировать все зависимые функции. Для сбора такого графа нужно знать имя компилируемой функции, чтобы в macroexpand можно было сделать запись о зависимости.

Сложнее бывает, когда случайно скобку не там поставил и не заметил.

По-моему, в SLIME, если открыть инспектор, можно увидеть поток и его позицию и даже открыть файл на этом месте. Хотя я не помню.
Ещё, если поток доступен (а он доступен через стек), можно сделать из него read-line один или более раз и тогда станет ясно.

Я хочу сделать restart вокруг compile-file, чтобы автоматизировать эти действия и чтобы можно было встать на позицию в файле. Все нужные компоненты (для лиспворкса) у меня уже есть, осталось только собрать их воедино, но вот сижу на форуме и руки ни до каких дел не доходят :-(

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

> Речь шла о запоминании графа зависимостей функций от макросов, чтобы

можно было при изменении макроса автоматически перекомпилировать все

зависимые функции.



M-x slime-who-macroexpands ?

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

Для SBCL оно работает на базе sb-introspect:who-macroexpands.

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

> а что с теми реализациями схемы, у которых есть swank-бекенд к SLIME? оно работает?

интерпретатор никто и не отменял, но мы же про компилятор

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

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

вот и не путайся и иди прочти, что такое инкрементальная компиляция

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

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

навесить хук на *macroexpand-function* (использовать стек), навесить макрос-перекрыть defun (заполнять стек, символ-это функция). Перекрыть defmacro (символ-это макрос), и при компиляции такого макроса через compile, раскручивать стек и перекомпилировать. Схематично как-то так. Чтобы перекрытые defmacro и defun сами такой граф собирали. Правда, с макросами, пишущими макрос или функцию хз что будет.

anonymous
()
Ответ на: комментарий от korvin_
интерпретатор никто и не отменял, но мы же про компилятор

Когда ты пишешь в ракете (define x 1) например, это то же самое, что ты в CL напишешь (compile (define x 1)). Все сразу компилируется в байткод и не перекомпилируется, пока не переопределишь. Ты видел, как выглядит байткод? Сделай (compile `anyfun) и посмотри, сразу все станет ясно.

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

Ну так ракет в машкод и не компилит кроме как jitom. А чего неожиданного я должен был увидеть от евалов в standalone executable?

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

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

> интерактивной разработки - вещь, конечно, удобная, но для написания

чего-то длиннее, чем пара тысяч строк, неприменимо принципиально


Измышлениями занимаетесь? На практике всё соверешнно наоборот.

CL же не ловит даже банальные опечатки


Очень часто даже проблемы с типами ловит при полном отсутствии их деклараций.

так что образ при таком подходе к разработке чрезвычайно быстро

превратится в принципиально неотлаживаемую какашку,



Вы так ничего и не понял? При чём тут образ?

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

Измышлениями занимаетесь? На практике всё соверешнно наоборот.

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

Очень часто даже проблемы с типами ловит при полном отсутствии их деклараций.

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

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

> Я, может, несколько неверно выразился.

Нет, вы совершенно неверно поняли смысл и последствия интерактивной разработки. Для надёжности программ от неё только плюс, при чём, большой.

То есть если предполагается, что программа может регулярно падать,

а затраты на отладку не принципиальны - то все ок.



Мои программы, почему-то, не падают.

как CL не может поймать unbound-переменную из-за иррациональной веры

в то, что кто-то ее определит в рантайме



Нет, дело не в этом, а в том, что это димамические переменные, которые используются специальным образом. Если динамическая переменная оказывается unbound, то это проблема в дизайне. Проблемы в дизайне никакой компилятор выявить не может.

Вот если я не намеренно попытался вызвать еще неопределенную

переменную, а просто сделал опечатку



То, естественно, получите предупреждение.

То есть либо интерактивная разработка, либо макросы.


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

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

> Написать то что-то большое можно - только вот надежность этого будет, мягко говоря, не очень.

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

даже варнингом не кинется по этому поводу

Зависит от реализации.

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

Нет, дело не в этом, а в том, что это димамические переменные, которые используются специальным образом. Если динамическая переменная оказывается unbound, то это проблема в дизайне.

Это обычная функция была, при чем тут динамические переменные? (defmacro yoba () (yobafun)), yobafun не определена и никакого варнинга. А на самом-то дело я хотел написать yoba-fun, да просто "-" пропустил...

Проблемы в дизайне никакой компилятор выявить не может.

SBCL - не может. Подавляющее большинство остальных компиляторов подобные проблемы в дизайне выявляют на раз.

То, естественно, получите предупреждение.

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

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

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

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

False. Описки и опечатки - это редкие ошибки.

Да, я ожидал такого ответа. Конечно же, Lisp-программист - это суровый мужчина, который не делает опечаток.

Зависит от реализации.

Я полагаю, мы тут говорим о конкретно SBCL.

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

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

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

> Это обычная функция была, при чем тут динамические переменные?

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

Подавляющее большинство остальных компиляторов подобные проблемы

в дизайне выявляют на раз.



Проблемы в дизайне? Вы запутались сами и путаете остальных.

Я даже проверил специально еще раз


Что вы проверяли? Там сыплются предупреждения. Прекратите заниматься дезинформацией.

Если все равно приходится регулярно перезапускать и

перекомпилировать, то это совершенно не отличается от остальных


способов разработки.



Вам не кажется, что дело в том, насколько часто? Я обычно перезапускаю SBCL пару раз в день.

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

Да, я ожидал такого ответа. Конечно же, Lisp-программист - это суровый мужчина, который не делает опечаток.

Да, на 100 логических приходится дай бог 1-2 опечатки. Тем более что во многих случаях я практически сразу (пока печатаю) вижу опечатался или нет благодаря подсказакам slime.

Я полагаю, мы тут говорим о конкретно SBCL.

CL-USER> (defun foo (a b)                                                                                               
           (+ a p))
; in: LAMBDA NIL                                                                                                        
;     (SB-INT:NAMED-LAMBDA FOO                                                                                          
;         (A B)                                                                                                         
;       (BLOCK FOO (+ A P)))                                                                                            
; ==>                                                                                                                   
;   #'(SB-INT:NAMED-LAMBDA FOO                                                                                          
;         (A B)                                                                                                         
;       (BLOCK FOO (+ A P)))                                                                                            
;                                                                                                                       
; caught STYLE-WARNING:                                                                                                 
;   The variable B is defined but never used.                                                                           
                                                                                                                        
;     (+ A P)                                                                                                           
;                                                                                                                       
; caught WARNING:                                                                                                       
;   undefined variable: P   

Вообще единственное, что позволяет такой подход - это быстро-быстро написать костыль, который будет _как-то_ работать на _каких-то_ исходных данных

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

А после того, как начинается отладка,

Она не начинается, она неразрывно связана с написанием кода. Тоже касается юнит тестов - они тут же сразу пишутся, проверяются и запускаются.

потому что если тебе надо прогнать серию юнит-тестов, например, то затратами на компиляцию и перезапуск можно со спокойной душой пренебрегать

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

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

здесь речь не об unbound, а об отсутствии функции, что совсем разные вещи.

А отсутствие ф-и в cl - это не unbound? Ну ладно, не важно.

Что вы проверяли? Там сыплются предупреждения. Прекратите заниматься дезинформацией.

Ну это смешно просто. неужели самому так трудно скомпилировать две строчки?

(defun SOOSNOLEY () `SOOSNOLEY)
(defmacro yoba () (SOOSNOLEY))

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

> А отсутствие ф-и в cl - это не unbound? Ну ладно, не важно.

Слушайте, как вы можете заниматься критикой CL совершенно в нём не разбираясь?

Ну это смешно просто. неужели самому так трудно скомпилировать

две строчки?



Проверяю, конечно, хоть результат и так очевиден. Но вы же постоянно разный код приводите, я не телепат. В данном коде вы получите ошибку компиляции при попытку использовать макрос yoba. А вовсе не run-time ошибку, как вы вероятно подумали. Так что не так?

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


(defun SOOSNOLEY () `SOOSNOLEY)
(defmacro yoba () (SOOSNOLEY))

Очень похоже на опечатку, да, очень. А вообще говоря.

 
CL-USER> (defun SOOSNOLEY () `SOOSNOLEY)
SOOSNOLEY                                                                                                               
CL-USER> (defmacro yoba () (SOOSNOLEY))
YOBA                                                                                                                    
CL-USER> (defun suck-my-dick-ignorant-anonymous ()                                                                      
           (yoba))
                                                                                                                        
;     (YOBA)                                                                                                            
;                                                                                                                       
; caught WARNING:                                                                                                       
;   undefined variable: SOOSNOLEY                                                                                       
;                                                                                                                       
; compilation unit finished                                                                                             
;   Undefined variable:                                                                                                 
;     SOOSNOLEY                                                                                                         
;   caught 1 WARNING condition                                                                                          
SUCK-MY-DICK-IGNORANT-ANONYMOUS   
anonymous
()
Ответ на: комментарий от anonymous

Да, на 100 логических приходится дай бог 1-2 опечатки.

Как же хорошо, что на практике все наоборот.

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

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

Она не начинается, она неразрывно связана с написанием кода. Тоже касается юнит тестов - они тут же сразу пишутся, проверяются и запускаются.

Так в чем проблема тогда там же делать перекомпиляцию? Или это идеологически - хоть убей, но влом одну кнопку нажать?

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

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

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

[quote] Очень похоже на опечатку, да, очень. [/quote] Ну да, вместо одной функции вызвал другую. Автозаполнение подвело.

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

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

CL-USER> (defun mytest () (yoba))

;     (YOBA)
; 
; caught WARNING:
;   undefined variable: SOOSNOLEY
; 
; compilation unit finished
;   Undefined variable:
;     SOOSNOLEY
;   caught 1 WARNING condition
archimag ★★★
()
Ответ на: комментарий от archimag

А вовсе не run-time ошибку, как вы вероятно подумали.

Как раз в рантайме, если йоба будет вызываться через (eval `(yoba)).

Так что не так?

Не так то, что SBCL даже варнинга не кинул. (эррор уже даже не прошу, лол)

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

>> Да, на 100 логических приходится дай бог 1-2 опечатки.

Как же хорошо, что на практике все наоборот.

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

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

> Не так то, что SBCL даже варнинга не кинул.

он правильно не кинул. Потому что макрос раскрывается потом. Использование и определение макроса - разные вещи.

Ты еще пожалуйся, что при выполнении (list 'a 'b) не выдало варнинга или ошибки, потому что символы a b not bound.

(эррор уже даже не прошу, лол)

И это уж точно не эррор, если определить переменную soosnoley в let или defparameter/defvar - макрос раскроется и выполнится без ошибок.

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

> Как раз в рантайме,

Да, при непосредственном выполнении в REPL будет runtime ошибка, это я протупил.

Не так то, что SBCL даже варнинга не кинул


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

Ещё раз, что именно не так? Макрос - это произвольная функция, которая может вернуть всё, что угодно. Проверить насколько это валидный код можно только в том месте, где его использует. Так что предупреждения будут в месте использования данного макроса, например, при компиляции функций.

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

Вообще, как известно, «недостатки это продолжение достоинств» (с) Макросы в CL могут опасны, но зато они могут позволять создавать решения подобные iterate на базе codewallker-а в несколько тысяч строк (это вам не банальный backquote). Возможно ли такая техника в Racket? Ибо я совершенно не представляю, что возможен «безопасный» вариант подобного решения. Зато тот же codewallker можно обложить тестами и контролировать каждый шаг его работы, это ведь самый обычный код на CL.

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

но зато они могут позволять создавать решения подобные iterate на базе codewallker-а в несколько тысяч строк

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

Возможно ли такая техника в Racket?

Такая - это какая? Написать кодеволкер, как в CL? Можно, конечно, если не боишься по лицу получить.

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

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

Да или нет? А достоинства или недостатки кодеволкера это предмет отдельного разговора.

Такая - это какая?


Аналог iterate на основе макросистемы Racket есть?

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

Да или нет?

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

Аналог iterate на основе макросистемы Racket есть?

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

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

> Но если тебе пришлось использовать в ракето-макросах

кодеволкер - значит тут что-то не то.


Т.е. можно видеть различия в том, что это не считается нормальным для ракеты, но было, вероятно, весьма популярным в CL во времена его создания. Я не затрагиваю вопрос о достоинствах кодоволкера, а только то, поощряет данная система его использование или нет.

Впрочем, если у вас есть на руках материал, который ясно и чётко указывает на то, что кодеволкер является идеей тупиковой, не нужной и есть более простые пути с большими возможностями для ВСЕХ случаев, то задачу признания макросов в CL устаревшими можно будет считать успешно решённой (имхо).

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

что его нельзя сделать?



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

Ясно, что подход ракеты чем-то обоснован и родился не на пустом месте. Так же ясно, что и подход CL имеет своё обоснование.

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

С другой стороны, эти подходы нельзя рассматривать независимо, вне контекста самих языков. А сравнение Racket vs CL не может быть однозначным, ибо Racket не является развитием идей, заложенных в CL, но развивает вообще несколько иное направление.

Вообщем, весь тред - сравнение апельсинов с яблоками.

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

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

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

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

Слушай, не юли. Признай, что racket в этом отношении слабее. Будь честен сам с собой.

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

> Чтобы перекрытые defmacro и defun сами такой граф собирали.
Это всё понятно, но, по-моему, это хрупко. Я когда-то давно пробовал и пришёл к выводу, что лучше defun не перекрывать. Во всяком случае, построение такого графа - недостаточный повод для этого.

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

Слушай, не юли. Признай, что racket в этом отношении слабее. Будь честен сам с собой.

Так ведь не слабее. При желании можно и с racket работать точно так же, но из соображений дизайна система модулей не поддерживает такого подхода. Так же, например, как Dr.Racket не отправляет автоматом в репл последнее объявление (хотя могла, то есть эта возможность просто была намеренно отключена). У Феллейсена даже пост в блоге есть на эту тему http://blog.racket-lang.org/2009/03/drscheme-repl-isnt-lisp.html. Ну а вообще, это все не важно, разговор изначально шел о макросах.

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

> Так ведь не слабее. При желании можно и с racket работать точно так же, но из соображений дизайна система модулей не поддерживает такого подхода.
Ты продолжаешь юлить. Последняя фраза внутреннее противоречива сама по себе, оно одновременно сочетает «можно и нельзя». Прямо журналистика какая-то!

http://blog.racket-lang.org/2009/03/drscheme-repl-isnt-lisp.html

За блог спасибо. Из него ясно видно, что язык заточен под студентов, а не под профессионалов. А это - совершенно разные целевые аудитории. Я, например, уже давным-давно не студент и зачем мне нужны учебные языки? Мне нужны промышленные.

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

На данный момент, я могу сделать такой вывод о racket:
1. Язык - учебный, а не промышленный. В общем-то и сразу у меня создалось такое впечатление, я, конечно же, пробовал DrScheme.
2. Исходя из этого, с точки зрения технологичности при профессиональной работе не даёт ничего по сравнению с cl.
3. Макросы в cl, если уметь ими пользоваться, достаточно удобны и безопасны. Да, возможно,у racket есть какие-то плюсы, но наверняка макросистему racket можно воспроизвести в рамках CL. Просто никто этого не делает, потому что в реальной жизни проблем с макросами очень немного. Единственное реальное (а не академическое) преимущество, которое я увидел за макросистемой racket - это возможность отследить исходный текст, в лиспе это не предусмотрено.
Вопросы гигиены легко решаются с помощью конструкций типа with-gensyms, их просто не нужно забывать ставить. Макросов не настолько много, чтобы это было обузой. Второе (косвенное) преимущество - писать макросы в racket тяжелее, а значит, к ним будут реже прибегать и можно ожидать, что они будут более продуманы. Хотя это больное место лиспа, его синтаксис настолько плох, что поневоле хочется его как-то подсластить, а это каждый делает по своему вкусу. Так что это второе преимущество макросов racket вытекает из общих (для CL и Scheme) недостатков лиспа.
4. JIT компиляция - это вообще плохо (как раз недавно было с моей подачи большое обсуждение, хотя каждый остался при своём мнении, но я-то свои выводы о языке привожу, а не твои). Даже с JIT, racket медленнее SBCL. Во всяком случае, у меня под рукой есть disassemble, а в racket его нет и быть не может.
5. Что касается вообще типизированного программирования, то оно возможно и в лиспе. Да, нет такого сахара с встроенными декларациями типов, но это можно исправить в рамках CL тем же способом (макросами).

И ты не ответил на ещё один вопрос - каков максимальный размер проекта под Racket (в мегабайтах исходного текста)?

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