Схема / Ракетка: Как сделать повтор при определении синтаксиса - PullRequest
1 голос
/ 17 февраля 2020

Я могу определить инфикс '+', как показано ниже в 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 с ~between, но без ~repeat.

Как использовать ~ между свойством для повторения элементов в синтаксисе ?

У меня есть обходной путь, но он не выглядит чисто множественным инфиксом +, нужно заключить каждую левую запись в скобки:

(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))

1 Ответ

3 голосов
/ 17 февраля 2020

Требуется комбинация ~seq и ...+.

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

Совпадения ~seq последовательность вещей без , требующая сгруппировать их в скобки, как это сделал ваш обходной путь.

...+ - это шаблон повторения, соответствующий одному или нескольким вещи, в отличие от нуля или более. Это гарантирует, что (f) не будет случайно интерпретирован как (+ f).

Еще одно примечание, когда вы определяете #%app напрямую, в отличие от определения под другим именем и затем переименования экспорта Вы должны быть особенно осторожны с неявным рекурсивным использованием. Например, (+ + x) - это бесконечный l oop. Чтобы исправить это, вы можете использовать racket:#%app в обоих выходах, например #'(racket:#%app + Value1 ... Value2).

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