Я не эксперт по тонкостям синтаксиса макросов Scheme, но я думаю эквивалентное определение try
:
(define-syntax try
(syntax-rules ()
((try var a b ...)
(letcc success
(letcc var (success a)) b ...))))
Мне гораздо проще прочитайте наверняка.
(try e <a> <b> <c>)
(любая версия, по крайней мере, в Racket) затем расширяется до
(letcc success
(letcc e
(success <a>))
<b> <c>)))
Итак, тогда, когда <a>
оценивается, e
продолжение, которое возвращает свои аргументы из внутренней letcc
формы, где они игнорируются. Если вызывается e
, то на этом вы заканчиваете, а затем <b>
и <c>
оцениваются обычным способом (я поместил туда только одну вещь, потому что могу, и это касается всего .
...
вещь). если e
не вызывается во время оценки <a>
, тогда вызывается success
, и это также продолжение, которое затем возвращает результат оценки <a>
из всей формы.
По крайней мере, я думаю, что так и происходит.
Ниже приведен фрагмент Ракетки, который я использовал для проверки, я понял вещи.
(module+ test
(require rackunit))
(define-syntax let/cc
(syntax-rules ()
((letcc var body ...)
(call-with-current-continuation
(lambda (var) body ... )))))
(define-syntax try
(syntax-rules ()
((try var a b ...)
(let/cc success
(let/cc var (success a)) b ...))))
(module+ test
(check-eqv?
(try fail (+ 1 1) 4)
2)
(check-eqv?
(try fail (fail '(2)) 4)
4)
(check-eqv?
(try fail
(begin 1 (fail) (error "failed to fail"))
4 5 6)
6))