Macros Racket宏省略语法
我有一个宏,当一个参数被传递时它就工作了,我想用…,将它扩展为接受n个参数,但是我在理解语法时遇到了困难 宏接受自定义语法,即key:val key:val,或接受过程 例如:(3种不同的用法) 定义:Macros Racket宏省略语法,macros,racket,ellipsis,Macros,Racket,Ellipsis,我有一个宏,当一个参数被传递时它就工作了,我想用…,将它扩展为接受n个参数,但是我在理解语法时遇到了困难 宏接受自定义语法,即key:val key:val,或接受过程 例如:(3种不同的用法) 定义: (define-syntax (schema-properties stx) (syntax-parse stx [(_ [(prop:expr ...)]) (with-syntax ([prop0 (make-prop-hash #'(prop ...))])
(define-syntax (schema-properties stx)
(syntax-parse stx
[(_ [(prop:expr ...)])
(with-syntax ([prop0 (make-prop-hash #'(prop ...))])
#'(list prop0))]))
(define-for-syntax (make-prop-hash stx)
(with-syntax ([(props ...) stx])
(if (regexp-match #px":"
(symbol->string (car (syntax->datum #'(props ...)))))
#'(pairs->hash 'props ...)
#'(props ...))))
这是可行的,因为它检查prop:expr语法是否存在“:”,如果存在,则将其传递给函数(pairs->hash'props…),否则,它只调用它(props…)
现在,我希望能够通过:
(schema-properties [(name:first-name type:string)
(name:last-name type:string)
(my-fn arg1 arg2 arg3)])
让它以同样的方式工作。但我现在处于省略号地狱,我的大脑不再正常工作
欢迎您提供任何见解。建议:使用帮助函数帮助处理嵌套。您的
schema properties
宏知道如何处理一个嵌套级别,您希望将其应用于多个子句。这与我们处理事物列表的原则相同:让一个助手来处理事物,然后将其应用到列表中。它有助于降低复杂性
对于您的代码,我们可以这样做:
#lang racket
(require (for-syntax syntax/parse))
(define-syntax (schema-properties stx)
(syntax-parse stx
[(_ [clause ...])
(with-syntax ([(transformed-clauses ...)
(map handle-clause (syntax->list #'(clause ...)))])
#'(list transformed-clauses ...))]))
;; handle-clause: clause-stx -> stx
(define-for-syntax (handle-clause a-clause)
(syntax-parse a-clause
[(prop:expr ...)
(make-prop-hash #'(prop ...))]))
(define-for-syntax (make-prop-hash stx)
(with-syntax ([(props ...) stx])
(if (regexp-match #px":"
(symbol->string (car (syntax->datum #'(props ...)))))
#'(pairs->hash 'props ...)
#'(props ...))))
;;; Let's try it out. I don't know what your definition of pairs->hash is,
;;; but it probably looks something like this:
(define (pairs->hash . pairs)
(define ht (make-hash))
(for ([p pairs])
(match (symbol->string p)
[(regexp #px"([-\\w]+):([-\\w]+)"
(list _ key value))
(hash-set! ht key value)]))
ht)
(schema-properties [(name:first-name type:string)
(name:last-name type:string)
(list 1 2 3)])
另一项建议:使用语法类帮助处理嵌套: 首先,定义一个语法类来识别key:value标识符(并使其组件字符串作为
key
和value
属性可用):
现在,将子句定义为一个序列(以一种方式处理)或任何其他内容(作为表达式处理,必须生成一个过程)。code
属性包含对每种子句的解释
(begin-for-syntax
(define-syntax-class clause
#:attributes (code)
(pattern (x:key-value-id ...)
#:with code #'(make-immutable-hash '((x.key . x.value) ...)))
(pattern proc
#:declare proc (expr/c #'(-> any))
#:with code #'(proc.c))))
现在,宏只是将各个部分放在一起:
(define-syntax (schema-properties stx)
(syntax-parse stx
[(_ [c:clause ...])
#'(list c.code ...)]))
像往常一样,丹尼立即做出了彻底的回应!非常感谢。那就更好了,谢谢。就我的技能水平而言,概念上有点密集,但我想是时候深入研究语法类了
(begin-for-syntax
(define-syntax-class clause
#:attributes (code)
(pattern (x:key-value-id ...)
#:with code #'(make-immutable-hash '((x.key . x.value) ...)))
(pattern proc
#:declare proc (expr/c #'(-> any))
#:with code #'(proc.c))))
(define-syntax (schema-properties stx)
(syntax-parse stx
[(_ [c:clause ...])
#'(list c.code ...)]))