Common Lisp - 符号计算引论 第七章“Applicative Programming” 学习周记
来源:互联网 发布:颜值有热度的网络句子 编辑:程序博客网 时间:2024/06/06 01:35
按照作者的说法,他准备介绍三种编程风格,首当其冲的就是本章了,本章的题目叫做Applicative Programming,直译叫“应用式编程”,网上查了,其实就是“函数式编程"的同义词,猜想Applicative Programming,想强调的是Applicative——高阶函数(high order function)用其他的函数和列表作为参数传入,并用这个传入的函数对列表进行计算然后得到一个结果。
一. 几个常用的built-in Common Lisp高阶函数
Common Lisp内建的几个高阶函数(书中叫Applicative Operator)有:
1. mapcar
从函数名就能很好地理解它的作用,调用该函数需要传递函数和列表作为参数,然后该函数依次对列表中每个元素(顶层元素,不解析嵌套列表)调用该函数,然后将得到的结果集拼接成列表输出,所以叫map(映射),比如,对(1 2 3 4 5)每个元素求平方,如果用C语言写可能会是这样:
for (i = 0; i < sz; i++) result[i] = input[i] * input[i];
而Lisp写出来则是:
(mapcar #’(lambda(n) (* n n)) ’(1 2 3 4 5))
这里用了lambda表达式来编写一个平方函数,当然也可以另外定义一个square然后传递给mapcar,mapcar不是只能操作一个列表,实际上我们可以传递多个列表进去,而相应的函数就要变为多参数函数或多元运算符,(mapcar #'+ '(1 3 5 7 9) '(2 4 6 8 10))可以将两个列表对应相加的结果返回。
2. find-if
参数为函数fn和列表lst,返回的结果为lst中第一个使fn为真的函数,可以带可选参数:from-end让find-if从后向前查找。
3. remove-if和remove-if-not
传入的参数为函数fn和列表lst,remove-if将列表中所有使函数fn为真的元素删除,而remove-if-not将使函数fn为真的元素保留,其他的删除。
4. reduce
归约函数,对一个列表进行操作,把列表中的元素用传入的函数参数进行计算,然后把计算得到的一个结果值返回,比如多个列表归并成一个:
(reduce #'append '(a b c) '(1 2 3) '(a a a))得到 '(a b c 1 2 3 a a a)
5. every
若传入的列表中每个元素都使参数函数fn为真,则every返回true,否则返回false
6. lambda表达式
用途很多,其中的一个用途就是与高阶函数搭配使用,在调用上述高阶函数时,常常不用单独定义一个命名函数,而是在高阶函数参数传递中随手写一个lambda表达式,之后该表达式作为匿名函数参数传入高阶函数,完成所需要的计算,使用lambda表达式常常使得程序紧凑,易读。
7. “function”特殊函数
若传递一个符号给该函数,则函数返回该符号代表的函数对象(Lisp中“符号”是一种数据类型,它可以表示某变量,可以表示某函数);若传递给它lambda表达式,则它返回该表达式对应的函数对象(词法闭包),一般用#'来表示,它使得函数在Lisp语言中成为“一等公民”——作为参数传递或作为结果返回。
(1)作为参数传递
这种情况常见于各种高阶函数的调用中,如果需要自己实现一个高阶函数,也要用到它,如:
(defun rights (fn) (funcall fn '(life is like a battle)));调用(rights #'length)得到5这里要注意的是变量fn的值是一个函数,但它自己不是函数名,因此(fn '(life is like a battle))是错误的,必须用funcall来调用fn绑定的那个函数对象
(2)作为结果返回
书上的例子,实现一个高阶函数,传入一个数字n,返回一个判断参数值是否大于n的谓词函数
(defun make-greater-than-predicate (n) #'(lambda (x) (> x n)))
该函数将返回一个谓词函数fn,fn接受一个参数x,并当x > n 时返回true,比如(make-greater-than-predicate 4)将返回一个谓词函数判断其参数是否大于4,那么
(find-if (make-greater-than-predicate 3) '(2 3 4 5 6 7 8 9))将返回第一个比3大的数4
8. trace和untrace工具
trace可以用来跟踪函数的执行,但是要注意,跟踪内建函数有时候可能会导致死循环的发生。
最后,给出一段Lisp程序,该程序是本章的大练习,实现了一个简单的知识系统,该知识系统用数据库表示砖块的颜色,大小,形状和位置等信息,然后用一个简单的模式匹配器去试图从中获取知识,比如模式’(b1 ? b2)试图找出b1和b2的关系,'(b1 color ?)试图查找b1的颜色信息。
(defparameter *database* '((b1 shape brick) (b1 color green) (b1 size small) (b1 supported-by b2) (b1 supported-by b3) (b2 shape brick) (b2 color red) (b2 size small) (b2 supports b1) (b2 left-of b3) (b3 shape brick) (b3 color red) (b3 size small) (b3 supports b1) (b3 right-of b2) (b4 shape pyramid) (b4 color blue) (b4 size large) (b4 supported-by b5) (b5 shape cube) (b5 color green) (b5 size large) (b5 supports b4) (b6 shape brick) (b6 color purple) (b6 size large)))(defun match-element (symbol1 symbol2) (or (equal symbol1 symbol2) (equal symbol2 '?)))(defun match-triple (entry pattern) (every #'match-element entry pattern))(defun fetch (pattern) (remove-if-not #'(lambda (entry) (match-triple entry pattern)) *database*))(defun color-pattern (block) (cons block '(color ?)))(defun support-pattern (block) (append '(? supports) (list block)))(defun supporters (block) (mapcar #'first (fetch (support-pattern block))))(defun shape-pattern (block) (cons block '(shape ?)))(defun supp-cube (block) (find-if #'(lambda (blk) (find-if #'(lambda (entry) (equal (third entry) 'cube))(fetch (shape-pattern blk)))) (supporters block)))(defun description (block) (reduce #'append (desc2 block)))(defun desc1 (block) (remove-if-not #'(lambda (entry) (equal (first entry) block)) *database*))(defun desc2 (block) (mapcar #'(lambda (entry) (cdr entry)) (desc1 block)))(defun description (block) (mapcar #'append (desc2 block)))
- Common Lisp - 符号计算引论 第七章“Applicative Programming” 学习周记
- Common Lisp:符号计算引论 第十一章 键盘练习
- Common Lisp 符号计算引论第八章——递归 学习笔记
- Common Lisp 符号计算引论第九章练习——画一元函数图像
- Common Lisp的学习
- common lisp 学习笔记
- 学习COMMON LISP总结
- Common Lisp 学习书目
- Common Lisp 学习笔记
- 学习common lisp 笔记二
- 学习Common lisp 笔记三
- 学习Common Lisp的好书
- 《ANSI Common Lisp》学习笔记
- Common Lisp --- 计算 3x+1 问题
- Practical Common Lisp学习笔记——之前记
- Common Lisp学习之七:LISP的面向对象编程
- Common Lisp
- Common Lisp
- jsp页面间跳转
- HDU1075:What Are You Talking About
- MongoDB 从入门到精通专题教程
- 异常类
- ubuntu 评测脚本
- Common Lisp - 符号计算引论 第七章“Applicative Programming” 学习周记
- div+css
- VS2008下用MFC 的MSComm控件编写串口程序
- [Linux] 常用命令集合
- 舍伍德算法改进快速排序
- 自制eclipse上的java编程助手软件
- 黑马程序员__JAVA基础__面向对象(一)
- oracle_Grid Infrastructure 启动的五大问题
- 掌握销售新主张销的是自己(1)