LINUX.ORG.RU

История изменений

Исправление 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?