实际上,我读的书的乐趣,但它可能会被视为功课。在任何情况下,我感觉不舒服本地状态变量在所有使用的语言......就拿这个代码:

(define flip
  (let ((count 0))
    (lambda ()
      (if (= 0 count)
          (begin (set! count 1) count)
          (begin (set! count 0) count)))))

为什么在1和0之间的这种代码替换?每到这个函数被调用时计数给出的值为0!一个Python当量将是:

class Flip:
    def __init__(self):
        pass
    def __call__(self):
        count = 0
        if count == 0:
            count = 1
            return count
        else:
            count = 0
            return count

此返回相同的事情每一次。我很困惑...

有帮助吗?

解决方案

我有编写编译器用于功能语言一点经验,所以也许的该函数是如何存储/表示在存储器是为了简短说明。每一个功能大致可看作是一对(E,F)其中,E是一组自由变量的,而F是函数本身的“代码”。当调用函数,它需要的值E和代替那些在F中的变量,并且然后使用这些值执行的代码。

所以,你的例子而言,您所定义的变量“翻转”是你让表达式返回的功能。这个函数是你的拉姆达里面的东西。因为“数”是拉姆达之外定义,它是一个自由变量,所以它的存储功能的环境。然后,每次调用(翻转)时,解释转到代码在lambda,看到它需要查找“计数”的值的环境中,这样做,改变它,并返回。这就是为什么每次调用时,存储在“数”的价值依然存在。

如果你想指望每次调用翻页时间为零,把let表达式的拉姆达里面,所以这是一个绑定变量,而不是自由变量。

其他提示

在拉姆达是一个闭合。这是引用一个自由变量(计数),其中,没有被本地定义或参数中的一个的功能,被绑定到最近的封闭词法环境。

被调用的函数是拉姆达,而不是“翻转”。翻转只是你给该所返回了(让...)表达的拉姆达的名称。

对于Python的,我不知道的语言,但它看起来像数应翻转对象的成员,而不是一个局部变量为呼叫

由于您的翻转功能实际上的返回功能(其内部拉姆达定义)

每个调用返回的函数时它修改它的环境。

如果你仔细想想的的的创建环境(并初始化计数为0),只有一次 - 当lambda函数返回给您

在某种意义上拉姆达为您创建一个功能对象其使用的环境中,其最后一帧中被初始化的单变量计数。每次调用函数时它修改它的环境。 如果调用的翻转的返回与不同环境中的另一函数对象第二次。 (计数初始化为0)然后可以独立地切换所述两个函子。

如果你想它已了解完全是如何工作的,你应该阅读有关的 environmantal模型

它更像

class Flip:
    def __init__(self):
        self.count = 0
    def __call__(self):
        if self.count == 0:
            self.count = 1
            return self.count
        else:
            self.count = 0
            return self.count

<强>更新与更多的解释: 在方案的功能是封闭的是“关闭”的周围自由变量count,这是在它外面的范围限定。该count是只用功能身体let定义方式,意味着该功能是可以访问它的唯一的事情 - 做count有效的一种私人可变状态附加到功能

这是这样的“对象”是在方案传统上创建在SICP - 具有let定义一组变量(实例变量,初始化为它们的初始值),并且在所述主体限定一组函数,其是已经共享访问实例变量“方法”。这就是为什么它是自然在这里使用一个Python类来表示这是怎么回事,有count是一个实例变量。

一个更直译成Python 3.x的将是这样的(请注意,这只是近似值,因为Python没有一个let(有限范围内的局部变量声明)的语法,并且不能使用Python的lambdas因为不采取语句):

count = 0

def flip():
    nonlocal count
    if count == 0:
        count = 1
        return count
    else:
        count = 0
        return count

# pretend count isn't in scope after this

与原始代码的问题是,它具有必要的样式的一个强烈的影响。更惯用解决方案将是:

(define (flip)
  (let ((flag #t))
    (lambda ()
      (set! flag (not flag))
      (if flag 1 0))))

要回答这个问题在你对此有何评论ooboo,你想返回功能的功能

(define make-flipper
  (lambda ()
    (let ((count 0))
      (lambda ()
    (let ((v count))
      (set! count (- 1 count))
      v)))))

;; test it
(let ((flip-1 (make-flipper)))
  (format #t "~s~%" (flip-1))  
  (format #t "~s~%" (flip-1))
  (format #t "~s~%" (flip-1))

  (let ((flip-2 (make-flipper)))
    (format #t "~s~%" (flip-2))
    (format #t "~s~%" (flip-2))
    (format #t "~s~%" (flip-2))))

您可以平凡改变设定!线,使之成为一个计数器,而不是一个导板(更有用的)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top