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

Ракетка имеет встроенную фундаментальную форму, 2 руки if, но в ней нет слова else, поэтому я хочу добавить к ней слово else.

Этот код работает:

(require syntax/parse/define)
(define-syntax-rule (myif Cond Form1 else Form2)
  (if Cond Form1 Form2)
)

(myif #t (displayln 1) else (displayln 2))

Однако myif является нежелательным в качестве ключевого слова, изменение его на if вызывает ошибку:

if: use does not match pattern: (if Cond Form1 else Form2)
in: (if #t (displayln 1) (displayln 2))

Как переопределить форму if?

Ответы [ 2 ]

2 голосов
/ 12 февраля 2020

Ответ выше является «правильным» на некотором уровне, но есть некоторые ошибки.

  1. define-syntax-rule не из syntax/parse/define. Если вы хотите использовать define-syntax-rule, вам не нужно (require syntax/parse/define).

  2. Что произойдет, когда я позвоню (if #t 1 2 3) с вашим if? else в вашем макросе - переменная шаблона, поэтому она может сопоставляться с чем угодно. Вы намерены позволить этому случиться? Если нет, то здесь вы можете использовать функции syntax/parse/define. Вы можете написать:

    (require syntax/parse/define)
    (define-simple-macro (if test-expr:expr 
                             {~datum then} 
                             then-expr:expr 
                             {~datum else} 
                             else-expr:expr)
      (racket:if test-expr then-expr else-expr))
    

    Так что (if 1 then 2 else 3) расширится до (racket:if 1 2 3), но (if 1 0 2 0 3) завершится с ошибкой.

1 голос
/ 12 февраля 2020

Спасибо @AlexKnauth за комментарий, я могу переопределить if, как показано ниже:

(require syntax/parse/define)
(require (only-in racket/base [if r-if]))

(define-syntax-rule (if Cond Form1 else Form2)
  (r-if Cond Form1 Form2)
)

(if #t (displayln 1) else (displayln 2))
...