2013-05-14 53 views
1

我正在为我的计划决赛和本地州的对象学习一直是一个艰难的课题。了解当地国家的对象 - 计划

这是我期末考试中的一个问题,我需要帮助。

(define (make-incrementer n) 
    (let ((old 0) 
     (new 0)) 
    (lambda() 
     (cond ((< new n) 
      (set! old new) 
      (set! new (+ new 1)) 
      old) 
      (else 
      (set! old 0) 
      (set! new 1) 
      old))))) 

(define a (make-incrementer 3)) 
(define b (make-incrementer 3)) 
(define c a) 

; 1) (a) 
; 2) (a) 

为什么当第二次调用a时返回1?我正在看代码,我们给它的n总是3.所以不会总是做else的情况吗?

+0

有时,理解是通过代码布局来促进的,因为这使得不同名称的范围**显而易见**。 – GoZoner 2013-05-14 02:28:05

+1

@GoZoner事实上,感谢上帝的C-M- \在emacs – jozefg 2013-05-14 02:31:09

+0

和'M-x untabify'发布到SO – GoZoner 2013-05-14 02:33:12

回答

3

欢迎来到关闭的美妙世界!这是关于Scheme如何工作的教科书示例。

所以make-counter返回一个函数,它有3个变量,它从它的封闭环境中捕获:n,old,new。在这种情况下,最初的环境中看起来像

_name_|_value_ 
n | 3 
old | 0 
new | 1 

在每次调用,它增加oldnew回绕到他们,如果他们比n更大。因为它使用的是set!,所以这个递增会改变lambda环境中的变量,但是由于这些变量是从周围环境中捕获的,所以它们也会在将来的所有调用中更改。

这就是为什么即使输入相同也会得到不同的回报。

如果这似乎是巫术,你可以认为它像物体更常用的语言:

如Python的:

class Foo(): 
    def __init__(self, n, m): 
     self.n = n 
     self.m = m 
    def count(self): 
     self.n += 1 
     if self.n == self.m: 
      self.n = 1 
     return self.n-1 

f = Foo(0, 2) 

f.count() # 1 
f.count() # 0 

这是除了这里我们是有点相同的基本思路更清楚地说明环境来自何处,self。在Scheme中,我们用lambda捕获周围的变量来模拟这一点。

如需更多信息,请查看SICP

+0

我没有得到的主要事情是,新旧不得不大于3的递增设置工作? – Dahnny012 2013-05-14 02:33:23

+0

@GoZoner是的,但这与这个解释没有什么关系...... – jozefg 2013-05-14 02:37:49

+0

@ user2036503是的,但是它们正在增加,'(set!new(+ 1 new))' – jozefg 2013-05-14 02:38:21

0

下面是一些例子,可能与拍摄时的概念帮助:

(define (always x) 
    (lambda rest x)) 
(define always-true (always #t)) 
(always-true #f) 
-> #t 

(define (add-n n) 
    (lambda (m) 
    (+ n m))) 
(define add-1 (add-n 1)) 
(add-1 10) 
-> 11 

(define (complement predicate) 
    (lambda (x) 
    (not (predicate x))) 
(define not-positive? (complement positive?)) 
(not-positive? -1) 
-> #t 

接下来是一个例子,其中拍摄的状态,在这种情况下l,发生了变异。这与您的情况类似,其中newold被捕获和修改。

(define (nexting l) 
    (lambda() 
    (if (null? l) 
     '() 
     (let ((answer (car l))) 
      (set! l (cdr l)) 
      answer)))) 
(define next-user (nexting '(Alice Bob David))) 
(next-user) 
-> Alice 
(next-user) 
-> Bob 
(next-user) 
-> David 
(next-user) 
'()