1

这个 R5RS 宏是我尝试过的,也是我想做的。球拍或其他实现不喜欢这个宏,正是我想要魔法发生的地方。

(define-syntax quote-unique
  (syntax-rules (magic end)

    ;; end case
    ((quote-unique magic processed end)
     'processed)

    ;; finished iteration
    ((quote-unique magic (processed ...) sym1 end rest ... )
     (quote-unique magic (processed ... sym1) rest ... end))

    ;; match (doesn't work since racket doesn't like sym1 twice in template)
    ;; but I'm looking for the same expression twice
    ((quote-unique magic processed sym1 sym1 . rest )
     (quote-unique magic processed sym1 . rest))

    ;; rotate
    ((quote-unique magic processed sym1 sym2 rest ... )
     (quote-unique magic processed sym1 rest ... sym2))

    ;; start iteration
    ((quote-unique rest ...)
     (quote-unique magic () rest ... end))))

这在 Common Lisp 中很容易:

(defmacro quote-unique ( &rest xs )
  (labels ((remove-duplicates (lis)
        (if lis
        (if (member (car lis) (cdr lis))
                (remove-duplicates (cdr lis))
            (cons (car lis) (remove-duplicates (cdr lis)))))))

     (list 'quote (remove-duplicates xs))))

我也一直在阅读定义语法入门并认为 is-eqv 的实现?会为我指出正确的方向,但似乎它不是在那里定义的宏。

如果在 R5RS 编译时不可能,那么如何使用 R6RS 来完成?

4

2 回答 2

3

Chris Jester-Young的remove-id答案示例可以在 R5RS 中表达:

(define-syntax remove-id
  (syntax-rules ()
    ((remove-id s (t ...))
     (letrec-syntax ((aux (syntax-rules (s)
                            ((aux p* ())
                             'p*)
                            ((aux p* (s . rest))
                             (aux p* rest))
                            ((aux (p (... ...)) (u . rest))
                             (aux (p (... ...) u) rest)))))
       (aux () (t ...))))))

(请注意,引用省略号(... ...)并不是严格意义上的 R5RS(仅 R7RS),而是仅用于使结果序列按给定顺序而不是反转。因此,通过添加另一个宏,您甚至可以放弃省略号。)

我希望这个例子能清楚地说明如何解决你原来的问题。如果可以使用卫生宏来解决某些问题,那么在使用 R6RS 之后可能不会标准化的过程宏或宏工具之前应该三思而后行。

于 2016-04-11T16:52:47.800 回答
2

您不能使用 来执行此操作syntax-rules,但您可以使用syntax-case, 通过使用使用 的守卫来执行此操作free-identifier=?。这是一个例子:

(define-syntax (remove-id stx)
  (syntax-case stx ()
    ((_ head ())
     #''())
    ((_ head (next tail ...)) (free-identifier=? #'head #'next)
     #'(remove-id head (tail ...)))
    ((_ head (next tail ...))
     #'(cons 'next (remove-id head (tail ...))))))

> (remove-id foo (foo bar baz qux foo bar))
; => (bar baz qux bar)

但是当然,如​​果你要使用syntax-case,有一个更简单的方法来实现你的quote-unique(这个实现使用 Racket 的自定义哈希表):

(require (for-syntax racket/dict))
(define-syntax (quote-unique stx)
  (define (id-dict ids)
    (foldl (lambda (id d)
             (dict-set d id #t))
           (make-immutable-custom-hash free-identifier=? (compose eq-hash-code syntax-e))
           (syntax-e ids)))
  (syntax-case stx ()
    ((_ ids ...)
     (with-syntax ((unique (dict-keys (id-dict #'(ids ...)))))
       #''unique))))
于 2013-06-12T21:56:57.810 回答