您的位置:首页 > 其它

Scheme和Common Lisp中对函数作为变量和返回值的处理方法差异

2013-12-30 23:24 274 查看
研究下Scheme和Lisp在lamba上的区别。今天晚上特别郁闷。本来想体会一下Lisp中函数作为第一等变量等柑橘,想不到却不知道载了多少个跟头。

Scheme

Scheme作为Lisp的一个方言,由MIT研发,并且GPL的协议下发布。大家可以从GNU官网上下载其源码,然后编译安装。Scheme相对与Lisp结合了Agol(不确定)。我们现在来看一下载Scheme语言中如何返回一个函数:

(define (repeat-2 fun)
(lambda (x) (fun (fun x)))
上述定义的函数将函数fun的功能重复两遍。其使用方法如下,假设定义了加1函数incf,

((repeat-2 incf) 1)
这样就将incf重复了两次。

Lisp

如果对Scheme的使用方式比较熟悉,那么在使用lisp实现时会觉得很奇怪。因为Lisp解析器根据变量的位置不同来决定变量是函数还是变量。Lisp中由两个函数boundp和fboundp,分别判断一个名字是否时一个有值的变量或者函数。载Lisp中lambda是宏,其展开时会调用function。举个例子。

(defun repeat-2 (fun)
(lambda (x) (funcall fun (funcall fun x))))
此时解析器会将其展开成如下:

(defun repeat-2 (fun)
(function lambda (x) (funcall fun (funcall fun x))))
Lisp允许我们只写lambda只是提供了一个语法糖,允许我们直接使用。注意到将函数作为变量值传递给函数时,调用方式不能像Scheme那样直接调用,而是需要funcall或者apply来调用。repeat-2返回将指定的函数重复2次的功能,返回的函数值,我们不能直接使用,也必须使用funcall或者apply。相对于Scheme好像有点复杂。

(funcall (repeat-2 #'incf) 1)
今晚在测试的时候使用Lisp系统自带的incf,结果报错,说incf是宏,不是函数。当时没注意,以为是调用方式出问题,便加了#'。后来又报错说值不能放函数定义。后来回过头来想起,原来incf是,他们封装了set的功能。于是自己写了incf-my,然后按照上面的方式执行一遍,结果OK。

后来Google搜索了相关的使用方法。原来Lisp中有两个Cell,姑且成为function cell和alue cell。所以允许函数名字和变量名字相同,解析器是根据位置来确定到底时解析成函数还是变量。通过之前说的boundp和fboundp来判断到底是变量还是函数。

本文完。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐