Scheme/Racket: 如何在定义语法中重复

Scheme/Racket: How to do repeating in defining syntax

我可以在 Racket 中定义中缀 '+' 如下:

(require syntax/parse/define (only-in racket (#%app racket:#%app)))
(define-syntax-parser #%app
  [(_ Value1 {~datum +} Value2)
  #'(+ Value1 Value2)]

  [(_ Xs ...) 
  #'(racket:#%app Xs ...)]
)
(displayln (1 + 2))

我想使用 ~between 添加多个中缀 '+' 但它不起作用:

(require syntax/parse/define (only-in racket (#%app racket:#%app)))
(define-syntax-parser #%app
  [(_ {~between {Value1 {~datum +}} 1 100} Value2)
  #'(+ Value1 Value2)]

  [(_ Xs ...) 
  #'(racket:#%app Xs ...)]
)
(displayln (1 + 2))

Racket 中的语法在这里:https://docs.racket-lang.org/syntax/stxparse-patterns.html with ~between but no ~repeat.

如何使用~between 属性来重复语法中的项目?

我有一个解决方法,但它看起来不是纯粹的多重中缀 +,需要将每个左边的条目括在方括号中:

(require syntax/parse/define (only-in racket (#%app racket:#%app)))
(define-syntax-parser #%app
  [(_ {Value1 {~datum +}} ... Value2)
  #'(+ Value1 ... Value2)]

  [(_ Xs ...) 
  #'(racket:#%app Xs ...)]
)
(displayln ({1 +} {2 +} 3))

你要的是~seq and ...+.

的组合
(define-syntax-parser #%app
  [(_ {~seq Value1 {~datum +}} ...+ Value2)
   #'(+ Value1 ... Value2)]
  [(_ Xs ...) 
   #'(racket:#%app Xs ...)])

~seq 匹配一系列事物 不需要像您的变通方法那样用括号将它们分组。

...+ 是一种重复模式,用于匹配一个或多个事物,而不是零个或多个。这确保 (f) 不会被意外解释为 (+ f).

另外请注意,当您直接定义 #%app 时,与使用不同名称定义然后重命名导出相反,您需要格外小心隐式递归使用。例如 (+ + x) 是一个无限循环。要解决这个问题,您可以在两个输出中使用 racket:#%app,例如 #'(racket:#%app + Value1 ... Value2).

(define-syntax-parser #%app
  [(_ {~seq Value1 {~datum +}} ...+ Value2)
   #'(racket:#%app + Value1 ... Value2)]
  [(_ Xs ...) 
   #'(racket:#%app Xs ...)])