Каждый вызов Let
создает новый набор переменных в среде, в которой оценивается основная часть Let
. Синтаксис Let
является "синтаксическим сахаром" для лямбды, которая оценивается с помощью переданных аргументов к этому, которые были оценены. Например
(let ((a (func object))
(b (func object2)))
(cons a b))
совпадает с написанием
((lambda (a b) (cons a b)) (func object) (func object2))
Таким образом, вы можете видеть, что в синтаксисе Let
сначала оцениваются аргументы, а затем тело, а определения a
и b
используются в локальной среде среды. Поэтому, если вы рекурсивно вызываете Let
, каждый раз, когда вы вводите тело вызова Let
, вы оцениваете тело в новой среде (потому что тело находится внутри недавно определенной лямбды), а определение аргументов определяется в локальной Let
области видимости будут другими (они на самом деле являются новыми переменными во вложенной среде, настроенной новой лямбдой, а не просто переменными, которые были видоизменены или «переопределены», как вы могли бы найти в цикле C ++).
Еще один способ сказать, что ваши переменные будут похожи на локальные переменные области видимости в рекурсивной функции C ++ ... для стекового фрейма каждой функции локально переменные области видимости будут иметь свое собственное определение и свою собственную память location ... они не являются мутированными переменными, как вы могли бы видеть в цикле, который повторно использует те же переменные памяти в локальной области видимости.
Надеюсь, это поможет,
Jason