Это работает, потому что ваше утверждение о том, что первый «аргумент» должен быть списком привязок, неверно. Синтаксис let
такой:
(let name ((binding expression) ...)
body ...)
Имя не является обязательным. У вас может быть ноль или более привязок. То, как макрос видит, что он назван или нет, зависит от того факта, что привязки должны быть списком, а имя обязательно должно быть идентификатором. Без имени это то же самое, что:
((lambda (binding ...)
body ...)
expression ...)
Однако с именем это становится:
((letrec ((name (lambda (binding ...)
body ...)))
name)
expression ...)
И, конечно же, letrec
определяется через let
:
(letrec ((name expression) ...)
body ...)
; ===
(let ((name 'undefined) ...)
(let ((tmp expression) ...)
(set! name tmp) ...)
body ...)
Таким образом, названный выше let превращается в это:
(((lambda (name)
((lambda (tmp) (set! name tmp)) (lambda (binding ...) body ...))
name)
'undefined)
expression ...)
Обратите внимание на то, что имя не привязано к фрейму, в котором оно было вызвано впервые. Его возвращают и тут же вызывают. Таким образом, среди выражений вы действительно можете вычислить name
из свободных переменных без того, чтобы именованные let
мешали этому:
(let ((name "sylwester"))
(let name ((cur (list name))
(n 2))
(if (zero? n)
cur
(name (append cur cur) (- n 1)))))
; ==> ("sylwester" "sylwester" "sylwester" "sylwester")
Использование define
теней этой привязки:
(let ((name "sylwester"))
(define (name cur n)
(if (zero? n)
cur
(name (append cur cur) (- n 1))))
(name (list name) 2))
; ==> (#<proc> #<proc> #<proc> #<proc>)
В отчете R6RS < href="http://www.r6rs.org/r6rs/final/html/r6rs/r6rs-Z-H-14.html#node_idx_394" rel="nofollow noreferrer">синтаксис для let
не демонстрирует более сложное имя let
, но добавляет ссылку на его описание в другом месте отчета. Вероятно, это связано с тем, что имя let
может быть громоздким и запутанным, когда вам нужны только локальные привязки. Это и то define
— две разные вещи верхнего уровня, а не самые запутанные части Scheme, поэтому, возможно, язык был бы легче понять для новичков, если бы они действительно имели разные имена, а не документировали разные места.
person
Sylwester
schedule
18.06.2017