Это по имени let, и это синтаксическое удобство.
(let f ([x y] ...)
...
(f ...)
...)
более или менее эквивалентно
(letrec ([f (λ (x ...)
...
(f ...)
...)])
(f y ...))
или, в подходящих контекстах,local define
, за которым следует вызов:
(define (outer ...)
(let inner ([x y] ...)
...
(inner ...)
...))
более или менее эквивалентен
(define (outer ...)
(define (inner x ...)
...
(inner ...)
...)
(inner y ...))
Хорошая вещь в именованном let
состоит в том, что он помещает определение ипервоначальный вызов локальной функции в том же месте.
Пещерные люди, подобные мне, которые используют CL, иногда используют макросы, подобные binding
, ниже, для реализации этого (обратите внимание, что это не рабочий код: все его сообщения об ошибкахнеясные шутки):
(defmacro binding (name/bindings &body bindings/decls/forms)
;; let / named let
(typecase name/bindings
(list
`(let ,name/bindings ,@bindings/decls/forms))
(symbol
(unless (not (null bindings/decls/forms))
(error "a syntax"))
(destructuring-bind (bindings . decls/forms) bindings/decls/forms
(unless (listp bindings)
(error "another syntax"))
(unless (listp decls/forms)
(error "yet another syntax"))
(multiple-value-bind (args inits)
(loop for binding in bindings
do (unless (and (listp binding)
(= (length binding) 2)
(symbolp (first binding)))
(error "a more subtle syntax"))
collect (first binding) into args
collect (second binding) into inits
finally (return (values args inits)))
`(labels ((,name/bindings ,args
,@decls/forms))
(,name/bindings ,@inits)))))
(t
(error "yet a different syntax"))))