Может ли кто-нибудь объяснить разницу просто? Я не думаю, что понимаю концепцию из учебников/сайтов, с которыми я консультировался.Смущает разница между let и let * в схеме
ответ
Если вы используете let
, вы не можете ссылаться на привязки, ранее определенные в том же выражении let
. Например, это не будет работать:
(let ((x 10)
(y (+ x 6))) ; error! unbound identifier in module in: x
y)
Но если вы используете let*
, то можно сослаться на предыдущие привязки в том же let*
выражение:
(let* ((x 10)
(y (+ x 6))) ; works fine
y)
=> 16
Это все here в документации.
Я не вижу его в документации (где ваши точки ссылки, текущая версия 5.3.6), поэтому я тоже был сбит с толку. В документации для 'let' говорится, что« Первая форма оценивает «val-exprs» слева направо, ... », поэтому неясно, что они оцениваются параллельно. – Alexey
@Alexey не оценивает их параллельно. Как сказано в документах: * «Первая форма оценивает« val-exprs »слева направо, создает новое местоположение для каждого« id »и помещает значения в места« * - значение, сначала они оцениваются и итоговые значения собираются, и только ***, тогда для каждого * 'id' * создаются *** новые местоположения, и значения помещаются каждый в своем местоположении. Вы все еще можете видеть последовательность, если один из * 'val-exprs' * мутирует хранилище (т. Е. Данные, такие как список или структура), к которому обращается последующий. –
Let
параллельно, (вид; смотри ниже)let*
является последовательным. Let
переводится как
((lambda(a b c) ... body ...)
a-value
b-value
c-value)
но let*
, как
((lambda(a)
((lambda(b)
((lambda(c) ... body ...)
c-value))
b-value))
a-value)
и, таким образом, создавая вложенные блоки области действия, где b-value
выражение может относиться к a
и c-value
выражение может относиться как к b
и a
. a-value
относится к внешнему виду. Это также эквивалентно
(let ((a a-value))
(let ((b b-value))
(let ((c c-value))
... body ...)))
Существует также letrec
, что позволяет рекурсивные привязки, где все переменные и выражения принадлежат к одному общему объему и могут относиться друг к другу (с некоторыми оговорками, относящихся к инициализации). Это эквивалентно либо
(let ((a *undefined*) (b *undefined*) (c *undefined*))
(set! a a-value)
(set! b b-value)
(set! c c-value)
... body ...)
(in Racket, также доступен как letrec*
на схеме, так как R6RS), или
(let ((a *undefined*) (b *undefined*) (c *undefined*))
(let ((_x_ a-value) (_y_ b-value) (_z_ c-value)) ; unique identifiers
(set! a _x_)
(set! b _y_)
(set! c _z_)
... body ...))
(in Scheme).
обновление: let
фактически не оценивает свои значения-выражения параллельно, это просто, что все они оцениваются в той же начальной среде, где появляется форма let
. Это также видно из перевода на основанное lambda
: сначала значение выражения вычисляются каждый в той же среде, внешней, и полученные значения собраны, и только затем новые места создаются для каждого идентификатора и значения ставятся каждый в своем местоположении. Мы все еще можем видеть последовательность, если одно из значений-выражений мутирует хранилище (т. Е. Данные, такие как список или структура), к которым обращается последующий.
Возможный дубликат [Scheme Confusing Let and Let \ *] (http: // stackoverflow.com/questions/8036840/schem-confusing-of-let-and-let) –
@DavidPfeffer - Кажется, это не обман. Этот вопрос задает очень специфическое взаимодействие вложенных 'let' и 'let *', в то время как этот запрашивает общий обзор. – Inaimathi
просто путают человеческое объяснение машинного выражения: o – Nishant