为什么 (c1) return 1、2、3 等等而不是 #<procedure:...make_counter.rkt:8:5>?
Why does (c1) return 1, 2, 3 ect.. and not #<procedure:...make_counter.rkt:8:5>?
这是来自环境模型部分的 SICP 课程:
(define make-counter
(lambda (n)
(lambda () (set! n (+ n 1))
n)))
下面,解释器说(make-counter 0)
是一个过程:
> (make-counter 0)
#<procedure:...make_counter.rkt:8:5>
下面,我定义c1
为(make-counter 0)
。
(define c1 (make-counter 0)
下面是我对 (c1)
return 计数器值而不是 "procedure"
的原因感到困惑的地方。
>(c1)
1
> (c1)
2
> (c1)
3
我的思考过程是,如果(c1)
指向一个过程,(make-counter)
,那么(c1)
应该return"procedure:...make_counter.rkt:8:5"
。
因为程序 -> 程序.
我知道应该发生什么,我只是在概念上对如何以及为什么感到困惑。
你的问题是什么?您是否怀疑它是否像名字所暗示的那样工作,或者您不明白它是如何工作的?
第一个可以在30秒内测试,我来回答第二个:
make-counter 是一个接受一个参数的过程。现在再看一下代码:return 是做什么用的?具有 0 个参数的过程。
因此执行 (c1)
将 return 从 1 开始的数字(如果从 0 开始)。
完整性:
Gambit v4.8.1
> (define make-counter
(lambda (n)
(lambda () (set! n (+ n 1))
n)))
> (define c1 (make-counter 0))
> (c1)
1
> (c1)
2
> (c1)
3
>
问题编辑后添加:
c1
是过程,但(c1)
是过程应用,在另一个编程世界中你会称之为"calling the procedure"。
> c1
#<procedure #2 c1>
> (c1)
1
顺便说一句,一段不错的函数式代码,如果您理解了这一点,您将以不同的方式看待编程。
更多问题 通过评论:
Now, its (make-counter 0). Working it by hand, I am not understanding
why n is not returned.
关于 c1
和 (c1)
的答案是一样的:
make-counter
returns lambda ()
,如果调用 lambda,n 只会被 returned。函数(在方案中:过程、lambda)是可以传递的值,函数式编程原则。你必须打电话给他们(正确的术语:申请)才能得到程序结果。
现在告诉我:在scheme中如何调用过程?
更多编辑:
好的,我们通过将它括在括号中来调用方案中的过程。
现在告诉我:(c1)
的替换步骤是什么?
My thinking process is that if (c1) points to a procedure, (make-counter), then (c1) should return "procedure:...make_counter.rkt:8:5".
这是错误的。
这里发生的事情是c1
“指向一个过程”,正如你所说,(实际上它是一个绑定到过程的名称)。
你应该记住,在 Scheme 中,形式 (f e1 e2 ... en)
是 调用 过程 f
的方式,将表达式 f
的值传递给它=13=].
因此,(c1)
与 c1
完全不同:它是一种 调用 过程 c1
的方法(没有参数).每次 interpreter/compiler 计算 (c1)
时,它都会调用增加值的过程 return。
你有
(define make-counter
(lambda (n)
(lambda () (set! n (+ n 1))
n)))
所以评价make-counter
returns
(lambda (n)
(lambda () (set! n (+ n 1))
n))
和评估 (make-counter 0)
只是用它的值替换该调用中的 make-counter
,然后继续作为
( (lambda (n)
(lambda () (set! n (+ n 1))
n))
0 )
=>
(let ((n 0))
(lambda () (set! n (+ n 1))
n))
所以闭包对象被创建并返回,
=>
(closure {environment1: ((n 0))} ; its own binding for `n`
(lambda () (set! n (+ n 1))
n))
所以在 (define c1 (make-counter 0))
这个闭包之后就是 c1
的值。
正在评估c1
returns它的值,上面的过程(闭包)。它的打印表示是依赖于实现的(显示例如 #<procedure>
或类似的东西)。
正在评估 (c1)
调用 这个过程,
(c1)
=>
( (closure {environment1: ((n 0))} ; its own binding for `n`
(lambda () (set! n (+ n 1))
n)) )
=>
(under {environment1: ((n 0))}
( (lambda () (set! n (+ n 1))
n)) )
不带任何参数调用 ((lambda () ...) )
只是评估它的主体而不创建任何新环境,因为参数列表是空的并且没有参数:
=>
(under {environment1: ((n 0))}
(set! n (+ n 1)) ; perform this first
n )
=>
(under {environment1: ((n 1))} ; <--- altered binding for `n`!
n ) ; now evaluate this and return its value
=>
1
它留下了改变 environment1
。当再次调用该过程(闭包)时,(c1)
,它的环境现在将包含 ((n 1))
,因此将更改为 ((n 2))
,等等
这是来自环境模型部分的 SICP 课程:
(define make-counter
(lambda (n)
(lambda () (set! n (+ n 1))
n)))
下面,解释器说(make-counter 0)
是一个过程:
> (make-counter 0)
#<procedure:...make_counter.rkt:8:5>
下面,我定义c1
为(make-counter 0)
。
(define c1 (make-counter 0)
下面是我对 (c1)
return 计数器值而不是 "procedure"
的原因感到困惑的地方。
>(c1)
1
> (c1)
2
> (c1)
3
我的思考过程是,如果(c1)
指向一个过程,(make-counter)
,那么(c1)
应该return"procedure:...make_counter.rkt:8:5"
。
因为程序 -> 程序.
我知道应该发生什么,我只是在概念上对如何以及为什么感到困惑。
你的问题是什么?您是否怀疑它是否像名字所暗示的那样工作,或者您不明白它是如何工作的?
第一个可以在30秒内测试,我来回答第二个:
make-counter 是一个接受一个参数的过程。现在再看一下代码:return 是做什么用的?具有 0 个参数的过程。
因此执行 (c1)
将 return 从 1 开始的数字(如果从 0 开始)。
完整性:
Gambit v4.8.1
> (define make-counter
(lambda (n)
(lambda () (set! n (+ n 1))
n)))
> (define c1 (make-counter 0))
> (c1)
1
> (c1)
2
> (c1)
3
>
问题编辑后添加:
c1
是过程,但(c1)
是过程应用,在另一个编程世界中你会称之为"calling the procedure"。
> c1
#<procedure #2 c1>
> (c1)
1
顺便说一句,一段不错的函数式代码,如果您理解了这一点,您将以不同的方式看待编程。
更多问题 通过评论:
Now, its (make-counter 0). Working it by hand, I am not understanding why n is not returned.
关于 c1
和 (c1)
的答案是一样的:
make-counter
returns lambda ()
,如果调用 lambda,n 只会被 returned。函数(在方案中:过程、lambda)是可以传递的值,函数式编程原则。你必须打电话给他们(正确的术语:申请)才能得到程序结果。
现在告诉我:在scheme中如何调用过程?
更多编辑:
好的,我们通过将它括在括号中来调用方案中的过程。
现在告诉我:(c1)
的替换步骤是什么?
My thinking process is that if (c1) points to a procedure, (make-counter), then (c1) should return "procedure:...make_counter.rkt:8:5".
这是错误的。
这里发生的事情是c1
“指向一个过程”,正如你所说,(实际上它是一个绑定到过程的名称)。
你应该记住,在 Scheme 中,形式 (f e1 e2 ... en)
是 调用 过程 f
的方式,将表达式 f
的值传递给它=13=].
因此,(c1)
与 c1
完全不同:它是一种 调用 过程 c1
的方法(没有参数).每次 interpreter/compiler 计算 (c1)
时,它都会调用增加值的过程 return。
你有
(define make-counter
(lambda (n)
(lambda () (set! n (+ n 1))
n)))
所以评价make-counter
returns
(lambda (n)
(lambda () (set! n (+ n 1))
n))
和评估 (make-counter 0)
只是用它的值替换该调用中的 make-counter
,然后继续作为
( (lambda (n)
(lambda () (set! n (+ n 1))
n))
0 )
=>
(let ((n 0))
(lambda () (set! n (+ n 1))
n))
所以闭包对象被创建并返回,
=>
(closure {environment1: ((n 0))} ; its own binding for `n`
(lambda () (set! n (+ n 1))
n))
所以在 (define c1 (make-counter 0))
这个闭包之后就是 c1
的值。
正在评估c1
returns它的值,上面的过程(闭包)。它的打印表示是依赖于实现的(显示例如 #<procedure>
或类似的东西)。
正在评估 (c1)
调用 这个过程,
(c1)
=>
( (closure {environment1: ((n 0))} ; its own binding for `n`
(lambda () (set! n (+ n 1))
n)) )
=>
(under {environment1: ((n 0))}
( (lambda () (set! n (+ n 1))
n)) )
不带任何参数调用 ((lambda () ...) )
只是评估它的主体而不创建任何新环境,因为参数列表是空的并且没有参数:
=>
(under {environment1: ((n 0))}
(set! n (+ n 1)) ; perform this first
n )
=>
(under {environment1: ((n 1))} ; <--- altered binding for `n`!
n ) ; now evaluate this and return its value
=>
1
它留下了改变 environment1
。当再次调用该过程(闭包)时,(c1)
,它的环境现在将包含 ((n 1))
,因此将更改为 ((n 2))
,等等