Как я могу сопоставить синтаксис в ракетке? - PullRequest
0 голосов
/ 30 июня 2018

Я хотел бы написать макрос, который соответствует заданному синтаксису if или cond, я попытался написать его так:

(define-syntax (foo stx)
  (syntax-case stx ()
    [(_ (if a b)) #'"if!"] 
    [(_ (cond a b) #'"cond!"]))

но это всегда соответствует первому случаю. Как я могу различить два случая?

1 Ответ

0 голосов
/ 30 июня 2018

В шаблоне syntax-case идентификатор соответствует чему угодно. Вы уже предполагаете, что это правда: когда вы пишете шаблон (if a b), предположительно вы предполагаете, что a будет соответствовать любому фрагменту синтаксиса, а не только литеральному идентификатору a. То же самое верно для идентификатора if - вы фактически не проверяете, что идентификатор равен if, вы просто сопоставляете любой фрагмент синтаксиса и привязываете его к переменной шаблона с именем if.

Для этого предназначен список литералов. Когда вы помещаете идентификатор в список литералов, он говорит syntax-case проверить этот конкретный идентификатор вместо привязки переменной шаблона. Таким образом, вы, вероятно, хотите это вместо:

(define-syntax (foo stx)
  (syntax-case stx (if cond)
    [(_ (if a b)) #'"if!"] 
    [(_ (cond a b) #'"cond!"]))

Тем не менее, обратите внимание, что syntax-case довольно старый, и Racket уже более десяти лет поставляется с лучшей библиотекой сопоставления синтаксиса, syntax/parse. Я бы порекомендовал его выше syntax-case во всех ситуациях. syntax/parse эквивалент вышеупомянутого макроса выглядит следующим образом:

(require (for-syntax syntax/parse))

(define-syntax (foo stx)
  (syntax-parse stx
    #:literals [if cond]
    [(_ (if a b)) #'"if!"] 
    [(_ (cond a b) #'"cond!"]))

… что в основном то же самое, но язык шаблонов syntax-parse гораздо богаче, чем язык syntax-case. Например, если вы хотите опустить объявление #:literals, вы можете аннотировать отдельные литеральные шаблоны, используя ~literal:

(define-syntax (foo stx)
  (syntax-parse stx
    [(_ ((~literal if) a b)) #'"if!"] 
    [(_ ((~literal cond) a b) #'"cond!"]))

Для получения дополнительной информации, см. Документацию для syntax/parse.

...