Это можно сделать, но макрос будет мешать так, что вы не можете делать все с помощью begin1
, как с begin
.
(define-syntax begin1
(syntax-rules ()
((_ expr0 expr1 exprn ...)
(begin
expr0
(let ((result expr1))
exprn ...
result)))))
Код, который не работает, таков:
(begin1
(define global1 10)
test3
(define global2 20))
Причина очевидна.Он расширяется до:
(begin1
(define global1 10)
(let ((result~1 test3))
(define global2 20)
result~1))
Второй define
будет изменен на letrec
, так что переменная global2
доступна только на время действия let
.У меня нет решения для этого, так как это требует, чтобы вы могли делать глобальные define
из замыкания.
begin1
довольно странная особенность.В Racket и, возможно, на других диалектах Scheme у нас есть begin0
, который возвращает результат первого выражения.Это очень полезно.например.Вот счетчик:
(define (get-counter from)
(lambda ()
(let ((tmp from))
(set! from (+ from 1))
tmp)))
А с begin0
:
(define (get-counter from)
(lambda ()
(begin0
from
(set! from (+ from 1)))))
В ракетке begin0
это примитив.Таким образом, эта форма поддерживается в полностью развернутой программе и, таким образом, реализована в C, как begin
..