Macros 关键字和默认参数宏干扰Racket中的变量参数
我正在使用本页()中提到的宏,它允许我使用{arg_name arg_value}作为默认参数和命名参数(不需要#:key_name)。它在其他方面工作正常,但它干扰了带有变量参数(fnname.vars)的函数声明。错误只是“语法错误”。如何纠正这一点?谢谢你的评论/回答 编辑:我当前的代码是:Macros 关键字和默认参数宏干扰Racket中的变量参数,macros,scheme,racket,Macros,Scheme,Racket,我正在使用本页()中提到的宏,它允许我使用{arg_name arg_value}作为默认参数和命名参数(不需要#:key_name)。它在其他方面工作正常,但它干扰了带有变量参数(fnname.vars)的函数声明。错误只是“语法错误”。如何纠正这一点?谢谢你的评论/回答 编辑:我当前的代码是: (require syntax/parse/define ; for define-simple-macro (only-in racket [define old-define]
(require syntax/parse/define ; for define-simple-macro
(only-in racket [define old-define] [#%app old-#%app])
(for-syntax syntax/stx)) ; for stx-map
(begin-for-syntax
;; identifier->keyword : Identifer -> (Syntaxof Keyword)
(define (identifier->keyword id)
(datum->syntax id (string->keyword (symbol->string (syntax-e id))) id id))
;; for use in define
(define-syntax-class arg-spec
[pattern name:id
;; a sequence of one thing
#:with (norm ...) #'(name)]
[pattern {name:id default-val:expr} ; rn: ch if {} needed here; since works well with [] here;
#:when (equal? #\{ (syntax-property this-syntax 'paren-shape))
#:with name-kw (identifier->keyword #'name)
;; a sequence of two things
#:with (norm ...) #'(name-kw {name default-val})]))
(define-syntax-parser define ; instead of define-simple-macro;
[(define x:id val:expr)
#'(old-define x val)]
[(define (fn arg:arg-spec ...) body ...+)
#'(old-define (fn arg.norm ... ...) body ...)])
(begin-for-syntax
;; for use in #%app
(define-syntax-class arg
[pattern arg:expr
#:when (not (equal? #\{ (syntax-property this-syntax 'paren-shape)))
;; a sequence of one thing
#:with (norm ...) #'(arg)]
[pattern {name:id arg:expr}
#:when (equal? #\{ (syntax-property this-syntax 'paren-shape))
#:with name-kw (identifier->keyword #'name)
;; a sequence of two things
#:with (norm ...) #'(name-kw arg)]))
(require (for-syntax (only-in racket [#%app app])))
(define-simple-macro (#%app fn arg:arg ...)
#:fail-when (app equal? #\{ (app syntax-property this-syntax 'paren-shape))
"function applications can't use `{`"
(old-#%app fn arg.norm ... ...))
我不知道该换哪一部分。如果删除最后一部分(定义简单宏),{}中的命名/默认参数不起作用
进一步编辑:我对代码进行了如下修改:
(define-syntax-parser define ; instead of define-simple-macro;
[(define x:id val:expr)
#'(old-define x val)]
[(define (fn arg:arg-spec ...) body ...+)
#'(old-define (fn arg.norm ... ...) body ...)]
[(define (fn . vars) body ...+)
#'(old-define (fn . vars) body ...)] )
它的工作原理是:
(define (testvars . vars)
(println (list? vars))
(for ((item vars))(println item)) )
(testvars 1 2 3)
#t
1
2
3
但是为什么我仍然需要“(定义简单宏..)”部分?还有,为什么我需要2“(开始语法..)”定义
再次编辑:进一步修改:
(define-syntax-parser define
[(define x:id val:expr)
#'(old-define x val)]
[(define (fn arg:arg-spec ...) body ...+)
#'(old-define (fn arg.norm ... ...) body ...)]
[(define (fn arg:arg-spec ... . vars) body ...+)
#'(old-define (fn arg.norm ... ... . vars) body ...)]
)
最后,上面的方法可以同时使用命名参数和变量参数,例如(fnname{x0}{y1}1020),感谢@AlexKnauth在下面的评论中提供的所有帮助。正如我们在评论中所指出的,您所要做的就是在
定义
宏中添加第三种情况,类似于第二种情况,但在模式中的arg:arg spec…
之后添加一个.rst
,在tem中的arg.norm…
之后添加一个盘子
第二个案例是
[(define (fn arg:arg-spec ...) body ...+)
#'(old-define (fn arg.norm ... ...) body ...)]
新案例类似,但添加了.rst
[(define (fn arg:arg-spec ... . rst) body ...+)
#'(old-define (fn arg.norm ... ... . rst) body ...)]
在上下文中看起来是这样的
(define-syntax-parser define
[(define x:id val:expr)
#'(old-define x val)]
[(define (fn arg:arg-spec ...) body ...+)
#'(old-define (fn arg.norm ... ...) body ...)]
[(define (fn arg:arg-spec ... . rst) body ...+)
#'(old-define (fn arg.norm ... ... . rst) body ...)]
)
该问题/答案中的define
宏不支持声明“rest”参数。当我编写它时,我不想用不相关的特性来扰乱实现。尽管事实上,您自己尝试扩展它应该不是很难。与定义简单宏不同,您必须使用两种情况,一种用于没有rest参数的情况,另一种用于有rest参数的情况。define
一个是您需要更改的,它已经用define syntax parser
编写。我已经忘记了,但这使它更容易。您只需在现有的define
宏中添加另一个大小写。最后一个define simple宏定义了\%app
宏,它重新定义了什么函数应用程序看起来是这样的。如果您不考虑这一点,您将能够调用(greet#:hello“hi”)
,但不能调用(greet[hello“hi”])
。您可能还应该添加修改后的define
宏作为答案,尽管您应该通过编写vars:id
来确保vars
是一个标识符,并且您应该确保您可以使用一些普通参数,后面跟着“.rst id”tooI会首先推荐,然后是