免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: xdshting
打印 上一主题 下一主题

能不能讲一下closure,正在看practical common lisp,就是理解不了这个概念 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-08 23:39 |显示全部楼层 |倒序浏览
书上的例子是
(let ((count 0)) #'(lambda () (setf count (1+ count))))

the reference to count inside the LAMBDA form should be legal according to the rules of lexical scoping. Yet the anonymous function containing the reference will be returned as the value of the LET form and can be invoked, via FUNCALL, by code that’s not in the scope of the LET. So what happens? As it turns out, when count is a lexical variable, it just works. The binding of count created when the flow of control entered the LET form will stick around for as long as needed, in this case for as long as someone holds onto a reference to the function object returned by the LET form. The anonymous function is called a closure because it “closes over” the binding created by the LET.
The key thing to understand about closures is that it’s the binding, not the value of the variable, that’s captured. Thus, a closure can not only access the value of the variables it closes over but can also assign new values that will persist between calls to the closure. For instance, you can capture the closure created by the previous expression in a global variable like this:

(defparameter *fn* (let ((count 0)) #'(lambda () (setf count (1+ count)))))

Then each time you invoke it, the value of count will increase by one.

CL-USER> (funcall *fn*)
1
CL-USER> (funcall *fn*)
2
CL-USER> (funcall *fn*)
3
基本上没看明白,而且红色的地方也有点奇怪

[ 本帖最后由 xdshting 于 2009-3-8 23:44 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2009-03-09 00:22 |显示全部楼层
每次运行(funcall (let ((count 0)) #'(lambda () (setf count (1+ count))))) 的值都是1

(defparameter *fn* (let ((count 0)) #'(lambda () (setf count (1+ count)))))

Then each time you invoke it, the value of count will increase by one.

CL-USER> (funcall *fn*)
1
CL-USER> (funcall *fn*)
2
CL-USER> (funcall *fn*)
3
这怎么解释,红色部分不就是说用defparameter代替后面的(let...)吗?
另外
(1+ count)与(+ 1 count)有区别吗?

谢谢

[ 本帖最后由 xdshting 于 2009-3-9 00:23 编辑 ]

论坛徽章:
0
3 [报告]
发表于 2009-03-09 00:50 |显示全部楼层
谢谢,现在明白一些了

看到您用
(funcall '+ 3 4)
我用
(funcall #'+ 3 4)

可以得到相同的结果,我觉得你用的形式不对阿,为什么能执行?

论坛徽章:
0
4 [报告]
发表于 2009-03-09 09:22 |显示全部楼层
谢谢了
再看ansi common lisp关于closure的介绍,又有一点不明白的地方
书上的例子
( let ((counter 0))
    (defun reset ()
       (setf counter 0))
    (defun stamp ()
       (setf counter (+ counter 1))))

CL-USER> ( l i s t (stamp) (stamp) ( reset ) (stamp))
          ( 1 2 0 1)

list是怎么看到stamp和reset函数的?这两个函数在let内部定义的阿

[ 本帖最后由 xdshting 于 2009-3-9 09:38 编辑 ]

论坛徽章:
0
5 [报告]
发表于 2009-03-09 11:05 |显示全部楼层
1,看了一些对closure的介绍

有一个感觉,有点像java里的封装吗,把free variable看作私有变量,只有通过对外接口去访问他

这样理解对不对?

2,另外,还是有点不明白,什么时候变量可以递增,什么时候他被重新初始化

(defparameter *fn* (let ((count 0)) #'(lambda () (setf count (1+ count)))))

以后通过 *fn* 去调用,let 只执行了一次,只有一个与 *fn* 关联的匿名函数(相应的私有空间)。

为什么只调用一次,是defparameter捣鬼吗?

论坛徽章:
0
6 [报告]
发表于 2009-03-09 11:27 |显示全部楼层
原帖由 win_hate 于 2009-3-9 11:12 发表
我查了一个:

http://community.schemewiki.org/?scheme-faq-language

scheme 的 faq,在里面的 Is there a way to define top-level closures?  一节说到:



所以你能在 let 外访问 let 中定义的函 ...


在很多地方都看到top-level这个词,您能不能详细解释以下

给我的感觉有一点像是全局的意思
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP