2013-05-14 50 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) 
'()