Корректны пункты 1, 2, 3, если вкладывать в это правильный смысл.
Число, и лямбда, возвращающая число - это разные вещи.
Для начала, symbol-macrolet работает иначе - к ,var мы привязываем не число, а выражение
(funcall ,sym), вот полный макроикспанд:
(sb-cltl2:macroexpand-all
'(lazy-let-1 ((x (print 5)))
(princ "im first")
(+ x x x)))=>
(LET (#:G906)
(SETQ #:G906
(LAMBDA ()
(FUNCALL (SETQ #:G906
(CONSTANTLY (PRINT 5))))))
(PRINC "im first")
(+ (FUNCALL #:G906) (FUNCALL #:G906) (FUNCALL #:G906) ))Теперь постараюсь по помеченным циферками вызовам описать суть:
1. В этом месте программы, до вычисления этого выражения, значением
#:G906 будет
(LAMBDA ()
(FUNCALL (SETQ #:G906
(CONSTANTLY (PRINT 5)))))Ну запускается, значит, нащ вычислятор funcall с параметром - этой лямбдой, и давай её вычислять.
А вот по порядку, что за чем вычисляется (метки слева просто для обозначения):
<A>: (print 5) - печатает 5 и возвращает число 5
<B>: (constantly <A>) === (constantly 5) возвращает (lambda () 5)
<C>: (SETQ #:G906 <B>) - присваивает лексическому биндингу #:G906 значение <B> и возвращает <B>
<D>: (FUNCALL <C>) - вычисляет лямбду (lambda () 5) и возвращает число 5.
Итак, выражение слева от `;; 1` возвращает число 5.
2. В здесь значение #:G906 уже равно (lambda () 5), потому оно вычисляется просто в 5.
3. См. 2.