简体   繁体   中英

Macro pattern not matching

Full source

So I have a macro for making objects, and it is used like:

(define ob 
  (class (a 10) (b 20)
         (set-a! (lambda (x) (set! a x)))
         (set-b! (lambda (x) (set! b x)))
         (foo (lambda (x)
                (* (+ a b) (- a b))))))

(ob 'a) -> 10
(ob 'b) -> 20
(ob 'set-a! 50)
(ob 'a) -> 50
(ob 'foo) -> 2100

I added another pattern for having public and private members,

(define ob
  (class private
         (a 10) (b 20)
         public
         (get-a (lambda (x) a))
         (set-a! (lambda (x) (set! a x)))))

and that works, but for some reason, it wont match this pattern:

(define ob2
  (class private
         (a 10) (b 20) (c '())
         public
         (get-a (lambda (x) a))
         (get-b (lambda (x) b))
         (set-a! (lambda (x) (set! a x)))
         (set-b! (lambda (x) (set! b x)))
         (push-c! (lambda (x)
                    (set! c (cons x c))))
         (pop-c! (lambda (x)
                   (if (not (eq? c '()))
                       (set! c (cdr c))
                       (error "stack empty!"))))))

The error message for trying to use ob2 is in the source

As far as I understand, the first example should not work either, and, in fact, I could not get it to work. I don't think you can use two ellipses on the same level. Therefore, it would be easier to define something like

(define-syntax class
  (syntax-rules (public private)
    ((class (public (?var ?val) ...) (private  (?var1 ?val1) ...))
     (list  (list ?var ?val) ... (list ?var1 ?val1) ...))))

However, if you have to do it all on the same syntactic level, you could do so by applying the macro recursively, along the following lines:

(define-syntax testclass
  (syntax-rules (public private)
    ((testclass public (var val) . rest)
     (testclass ((var val)) public . rest))
    ((testclass ((var val) ...) public (var1 val1) . rest)
     (testclass ((var val) ... (var1 val1)) public . rest))
    ((testclass lst public private . rest)
     (list (quote lst) (quote rest)))))

In order to make this more robust, you will have to add rules for empty public and private expressions.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM