Scheme 使用lambda模拟银行余额提取行为
我在读书 该解决方案提出了暴露Scheme 使用lambda模拟银行余额提取行为,scheme,sicp,Scheme,Sicp,我在读书 该解决方案提出了暴露平衡状态的问题,作为解决方案,引入局部变量 (define new-withdraw (let ((balance 100)) (lambda (amount) ;; (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds"))))
平衡状态的问题,作为解决方案,引入局部变量
(define new-withdraw
(let ((balance 100))
(lambda (amount) ;;
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))))
> (new-withdraw 40)
;Value: 60
lambda
也被引入,甚至认为它可以被改写为
(define (new-withdraw-2 amount)
(let ((balance 100))
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds")))
;Value: new-withdraw-2
8 error> (new-withdraw-2 30)
;Value: 70
我认为在这里应用lambda
似乎没有必要。我遗漏了什么?第三个函数与第二个函数非常不同,因为在它中,每次进行取款时,都会计算结果值100-金额(函数的参数),而在第二个函数中,有一个初始余额100,每次进行取款时,它从当前余额中减损
因此,new-draw-2
并没有为银行账户建模,该函数只是定义f(x)=100-x
的一种精细方法
为什么这两种功能如此不同,即使它们表面上看起来很相似
不同之处在于let
的语义:在第一种情况下,在new draw
中,let
引入一个新变量balance
,该变量建立一个新的“环境”,然后返回一个新函数(内部lambda
),变量余额
是外部变量。因此,每次调用返回的函数时,都会访问同一个变量并减小其值。下次调用它时,它将通过同一个变量发现上一次调用中减少的值。
内部函数等对象称为“闭包”,因为函数与外部环境是严格连接的,与环境形成一种状态“隐藏”在函数中,并在函数的不同调用之间持久化
相反,在第二种情况下,let
位于函数new-draw-2
:这意味着每次调用函数时,都会定义一个新的变量balance
,它建立了一个新的环境,函数本地的,变量被初始化为100,然后减小(设置时)
). 但当函数终止并返回新的平衡时,函数的本地环境将丢失,下次调用函数时,将再次建立一个新环境,变量平衡再次初始化为100
(define (new-withdraw-2 amount)
(let ((balance 100))
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds")))
;Value: new-withdraw-2
8 error> (new-withdraw-2 30)
;Value: 70
(define new-withdraw
(let ((balance 100))
(lambda (amount) ;;
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds"))))
> (new-withdraw 40)
;Value: 60
> (new-withdraw 30)
;Value: 30 ; equal to 60 - 30
(define (new-withdraw-2 amount)
(let ((balance 100))
(if (>= balance amount)
(begin (set! balance (- balance amount))
balance)
"Insufficient funds")))
> (new-withdraw-2 40)
;Value: 60
>(new-withdraw-2 30)
;Value: 70 ; equal to 100 - 30