Это то же самое, что и let
и letrec
. С let
вы не можете ожидать, что привязка существует при оценке значений. Это влияет только на создание процедуры/лямбда/замыкания, поскольку все процедуры вызываются в среде, в которой они созданы.
(define (test v)
(list 'default v))
(let ((test (lambda (v)
(if (zero? v)
(list 0)
(cons v (test (- v 1)))))))
(test 5))
; ==> (5 default 4)
(letrec ((test (lambda (v)
(if (zero? v)
(list 0)
(cons v (test (- v 1)))))))
(test 5))
; ==> (5 4 3 2 1 0)
Таким образом, в примере let
локальный let
не находится в теле замыкания, потому что он не существует при оценке значений. На практике, если вы расширите let
до его эквивалентной лямбда-формы, вы поймете, почему он вызывает глобальный test
:
((lambda (test) (test 5))
(lambda (v)
(if (zero? v)
(list 0)
(cons v (test (- v 1))))))
Вы понимаете, почему он не звонит сам себе? letrec
специально создан для создания локальных процедур, которые сами по себе являются обязательными для решения этой небольшой проблемы. Для синтаксических правил он имеет те же свойства привязки для похожих имен, но мы имеем дело с синтаксисом, поэтому нам нужно, чтобы шаги не зависели от арифметики времени выполнения:
(define-syntax stest
(syntax-rules ()
((_ v . rest) '(default v))))
(let-syntax ((stest (syntax-rules ()
((_ v . rest) (cons 'v (stest . rest)))
((_) '()))))
(stest 5 4 3 2 1 0))
; ==> (5 default 4)
(letrec-syntax ((stest (syntax-rules ()
((_ v . rest) (cons 'v (stest . rest)))
((_) '()))))
(stest 5 4 3 2 1 0))
; ==> (5 4 3 2 1 0)
Опять же, letrec-syntax
обеспечивает доступность stest
в среде преобразователя syntax-rules
, чтобы он соответствовал самому себе, а не макросу верхнего уровня.
Что касается ваших примеров, то они не Scheme. Возможно, они будут работать в какой-то конкретной реализации схемы как дополнительная функциональность де-факто, но они не будут работать ни в одной реализации R5RS, R6RS или R7RS, как в моих примерах. R6RS имеет syntax-case
в качестве дополнительного трансформатора, и я предполагаю, что R7RS-large также будет иметь дополнительные трансформаторы. Если вам нужно поведение де-факто, вам нужно пометить конкретную реализацию.
person
Sylwester
schedule
11.04.2020