История изменений
Исправление monk, (текущая версия) :
в отличие от CL macroexpand, Racket expand раскрывает вообще все макросы, а не только топовый.
macroexpand — тоже все. expand-once <=> macroexpand-1.
Во-первых скопировать
Я с середины пытался помечать. С хвоста действительно работает.
во-вторых результат макроэкспанда не всегда можно скопировать из-за gensym.
Скопировать можно всегда.
CL-USER> (macroexpand '(loop :for i :from 1 :to 10 :collect i))
(BLOCK NIL
(LET ((I 1))
(DECLARE (TYPE (AND REAL NUMBER) I))
(SB-LOOP::WITH-LOOP-LIST-COLLECTION-HEAD (#:LOOP-LIST-HEAD-1148
#:LOOP-LIST-TAIL-1149)
(SB-LOOP::LOOP-BODY NIL
(NIL NIL (WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
((SB-LOOP::LOOP-COLLECT-RPLACD
(#:LOOP-LIST-HEAD-1148 #:LOOP-LIST-TAIL-1149)
(LIST I)))
(NIL (SB-LOOP::LOOP-REALLY-DESETQ I (1+ I))
(WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
((RETURN-FROM NIL
(SB-LOOP::LOOP-COLLECT-ANSWER
#:LOOP-LIST-HEAD-1148)))))))
С аналогичным Racket'овским хуже:
> (syntax->datum (expand '(for/list ([fold-var (in-range 1 10)]) fold-var)))
'(#%app
alt-reverse
(let-values (((start) '1) ((end) '10) ((inc) '1))
(if (if (#%app real? start) (if (#%app real? end) (#%app real? inc) '#f) '#f) (#%app void) (let-values () (#%app in-range start end inc)))
(#%app
(letrec-values (((for-loop)
(lambda (fold-var pos)
(if (#%app unsafe-fx< pos end)
(let-values (((fold-var) pos))
(if '#t
(let-values (((fold-var)
(let-values (((fold-var) fold-var)) (let-values () (#%app cons (let-values () fold-var) fold-var)))))
(if '#t (#%app for-loop fold-var (#%app unsafe-fx+ pos inc)) fold-var))
fold-var))
fold-var))))
for-loop)
null
start)))
Как я должен догадаться, что в (#%app cons (let-values () fold-var) fold-var)) разные имена fold-var?
Исходная версия monk, :
в отличие от CL macroexpand, Racket expand раскрывает вообще все макросы, а не только топовый.
macroexpand — тоже все. expand-once <=> macroexpand-1.
Во-первых скопировать
Я с середины пытался помечать. С хвоста действительно работает.
во-вторых результат макроэкспанда не всегда можно скопировать из-за gensym.
Скопировать можно всегда.
CL-USER> (BLOCK NIL
(LET ((I 1))
(DECLARE (TYPE (AND REAL NUMBER) I))
(SB-LOOP::WITH-LOOP-LIST-COLLECTION-HEAD (#:LOOP-LIST-HEAD-1148
#:LOOP-LIST-TAIL-1149)
(SB-LOOP::LOOP-BODY NIL
(NIL NIL (WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
((SB-LOOP::LOOP-COLLECT-RPLACD
(#:LOOP-LIST-HEAD-1148 #:LOOP-LIST-TAIL-1149)
(LIST I)))
(NIL (SB-LOOP::LOOP-REALLY-DESETQ I (1+ I))
(WHEN (> I '10) (GO SB-LOOP::END-LOOP)) NIL)
((RETURN-FROM NIL
(SB-LOOP::LOOP-COLLECT-ANSWER
#:LOOP-LIST-HEAD-1148)))))))
С аналогичным Racket'овским хуже:
> (syntax->datum (expand '(for/list ([fold-var (in-range 1 10)]) fold-var)))
'(#%app
alt-reverse
(let-values (((start) '1) ((end) '10) ((inc) '1))
(if (if (#%app real? start) (if (#%app real? end) (#%app real? inc) '#f) '#f) (#%app void) (let-values () (#%app in-range start end inc)))
(#%app
(letrec-values (((for-loop)
(lambda (fold-var pos)
(if (#%app unsafe-fx< pos end)
(let-values (((fold-var) pos))
(if '#t
(let-values (((fold-var)
(let-values (((fold-var) fold-var)) (let-values () (#%app cons (let-values () fold-var) fold-var)))))
(if '#t (#%app for-loop fold-var (#%app unsafe-fx+ pos inc)) fold-var))
fold-var))
fold-var))))
for-loop)
null
start)))
Как я должен догадаться, что в (#%app cons (let-values () fold-var) fold-var)) разные имена fold-var?