Я запутался в макросе схемы

(define-syntax test

  (syntax-rules ()

    ((_ (head ... (x y) . tail))

     (syntax-error

      'tail

      "tail is"))

    ((_ any ...)

     (syntax-error "fallback"))))

Почему (test (1 7 (2 4) 34)) не соответствует первому правилу

2
Jiacheng Wang 31 Май 2019 в 07:32

2 ответа

Лучший ответ

Синтаксис правил сопоставления с образцом является жадным и не возвращается к тому же шаблону. head ... совпадает с (1 7 (2 4)), но 34 не совпадает с (x y) и поэтому не может быть выполнен. Если вы ожидаете только один элемент после того, как вы можете сделать это:

(define-syntax test
  (syntax-rules ()
    ((_ (head ... (x y) last-element))
     (syntax-error
      'last-element
      "last element is"))
    ((_ any ...)
     (syntax-error "fallback"))))

Если вы пытаетесь получить ноль или более элементов после последнего списка из двух, вам нужно немного помассировать его, если вы все еще хотите использовать syntax-rules:

(define-syntax test
  (syntax-rules (build)
    ((_ build m post (x y) . tail)
     (test build #t () . tail))
    ((_ build m (post ...) any . tail)
     (test build m (post ... any) . tail))
    ((_ build #t post)
     (syntax-error
      'post
      "tail is"))
    ((_ (head ...))
     (test build #f () head ...))
    ((_ any ...)
     (syntax-error "fallback"))))

Символ в шаблоне соответствует чему угодно. Вот почему шаблон (x y) должен идти первым, поскольку any также соответствует (2 4). например. для (test (1 7 (2 4) 34 (3 4 5))) пост будет (34 (3 4 5)), поскольку ни один из этих элементов не соответствует (x y), но оба соответствуют any.

Обратите внимание, что syntax-error не является частью Схемы.

1
Sylwester 1 Июн 2019 в 16:55

Список - это пара, чья cdr равна (), поэтому ваш вклад рассматривается так:

(1 7 (2 4) 34 . ())

Таким образом, (2 4) используется head, а 34 не совпадает с (x y).

3
Takashi Kato 31 Май 2019 в 06:45