Macros 关键字和默认参数宏干扰Racket中的变量参数

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]

我正在使用本页()中提到的宏,它允许我使用{arg_name arg_value}作为默认参数和命名参数(不需要#:key_name)。它在其他方面工作正常,但它干扰了带有变量参数(fnname.vars)的函数声明。错误只是“语法错误”。如何纠正这一点?谢谢你的评论/回答

编辑:我当前的代码是:

(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会首先推荐,然后是