Отсутствует аргумент в синтаксических правилах вызова макроса Hygieni c из примера Scheme R5RS - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть еще один вопрос о макросах Hygieni c в схеме, рассмотрим пример из R5RS

(let-syntax ((when (syntax-rules ()
                     ((when test stmt1 stmt2 ...)
                      (if test
                          (begin stmt1
                                 stmt2 ...))))))
  (let ((if #t))
    (when if (set! if 'now))
    if))

Почему это соответствует, если шаблон имеет 3 аргумента и многоточие, которые могут совпадать пустой список?

Он вызывается с 2 аргументами if и (set! if 'now). С чем следует связать ..., если stmt2 можно связать с пустым списком? Это не Лиспы, если ... это просто ничто. Это правда?

Каким должно быть расширение, когда в этом контексте? Каково значение stmt2?

Почему это не работает, но первый код работает?

(let-syntax ((when (syntax-rules ()
                     ((when test stmt1 stmt2 ...)
                      (if test
                          (begin stmt1
                                 stmt2 ...))))))
    (when if 10))

это работает в Kawa, но не в Guile, заключается в том, что ошибка в Guile, и он на самом деле должен работать как в Kawa?

И еще один вопрос, почему он не оценивается в nil? Если следующий элемент в списке после 10, равен nil, значит stmt2 должен быть nil? R5RS не очень помогает в этом отношении.

Я спрашиваю об этом, потому что я только что закончил схему переименования для моей макросистемы в Схеме LIPS, и когда я сопоставляюсь с образцом, у меня есть сравнение stmt2 и nil, а также осталось .... Следует ли в этом случае ... просто игнорировать, а stmt2 должно быть nil? И должно совпадать даже с тем, что в шаблоне на один символ меньше? Это действительно сбивает с толку.

Каким должно быть расширение последнего фрагмента кода?

РЕДАКТИРОВАТЬ:

Еще одна мысль

(let-syntax ((when (syntax-rules ()
                     ((when test stmt1 . stmt2)
                      (if test
                          (begin stmt1
                                 stmt2))))))
    (when if 10))

Это работает в Kawa и возвращает nil, как и ожидалось, но в Guile оно выдает исключение, я считаю, что схема Kawa будет лучше в следующем выражении c.

Но почему это даже соответствует шаблону, если мало аргументов?

1 Ответ

1 голос
/ 14 апреля 2020

Да. Очень нелепо, что у нас есть модификатор ..., который меняет значение элемента впереди. например. something ... в основном похож на . something, за исключением того, что он работает с такими структурами:

(define-syntax my-let
  (syntax-rules ()
    ((_ ((a b) ...)
        body1 bodyn ...)
     ((lambda (a ...) 
        body1 bodyn ...) 
      b ...))))

Обратите внимание, что я использую body1 ro требует по крайней мере одно выражение в теле, так как bodyn ... может быть ноль или больше элементов. Это обернется:

(my-let ()
  test)
==> 
((lambda () test))

Так же как и

(my-let ((a b) (c d))
  test1 test2)
==> 
((lambda (a c)
   test1 test2)
 b 
 d)

Мой пример не может быть переписан с использованием синтаксиса cons, но в основном использование . работает так же, как остальные аргументы в шаблоне и . в цитате:

'(a b . (c d)) 
; ==> (a b c d)

Ваш when не будет работать с более чем одним выражением. например.

(let-syntax ((when (syntax-rules ()
                     ((when test stmt1 . stmt2)
                      (if test
                          (begin stmt1
                                 stmt2))))))
    (define if #t)
    (when if (display 'true) #t))

Представьте, что все привязки отчетов также существуют с префиксом r5rs:. Расширение станет:

(r5rs:if if
         (begin (display 'true)
                (#t)))
; ERROR: Application not a procedure: #t

Это правильно:

(let-syntax ((when (syntax-rules ()
                     ((when test stmt1 . stmt2)
                      (if test
                          (begin stmt1
                                 . stmt2))))))
    (define if #t)
    (when if (display 'true) #t))
; ==> #t (prints true)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...