Это не полностью эквивалентно. define
в теле процедуры больше похож на letrec
, поэтому вы можете удивиться, что не можете использовать значение, привязанное в define
, пока все они не будут завершены и тело процедуры не будет выполнено. Представьте, что вы хотите сделать x + y * z:
(define (test x y z)
(let ((ytimesz (* y z)))
(let ((sum (+ x ytimesz)))
(dosomething sum))))
Причина, по которой у вас есть вложенный let, заключается в том, что к ytimesz
нельзя получить доступ в том же let, в котором он был создан. У нас есть еще одна специальная форма для этого let*
(define (test x y z)
(let* ((ytimesz (* y z)) (sum (+ x ytimesz)))
(dosomething sum)))
letrec
и letrec*
похожи, но допускают рекурсию, поэтому в лямбде вы можете вызвать один из других связанных членов или самого себя. Теперь, в зависимости от версии Scheme, которую вы используете, вы получите одно из них при написании:
(define (test x y z)
(define ytimesz (* y z))
(define answer (+ x ytimesz)) ;might work, might not
(dosomething answer))
В #!R7RS
, #!R6RS
и #!Racket
это нормально, так как это определено как letrec*
.
В #!R5RS
, однако, это вообще не сработает. Перезапись выполняется как letrec
и инициализирует все переменные (ytimesz
и answer
) неопределенным значением, затем назначает оценку выражений временным переменным перед set!
-вводом переменных в значения временных значений, чтобы убедиться, что все использование любое из них заканчивается неопределенными значениями и некоторыми даже сигнальными ошибками (Racket делает в режиме R5RS. Для лямбда-выражений, где привязки в теле оцениваются во время вызова, это не проблема, и для этих letrec
и внутренних define
это изначально предназначался для.
Я использую define
для хранения простых значений и процедур. Во-вторых, я думаю, что мне нужно использовать заранее рассчитанное значение, я могу переписать все это на let*
или объединить define
и простое let
.
person
Sylwester
schedule
18.02.2014