我以为的函数式编程
2015-01-07 01:14
411 查看
函数式编程
函数式编程(functional programming)的思想相对于命令式编程(imperative programming),告诉计算机你要什么而不是告诉它要怎么做,举个例子:(defun fun(x) (list 'a (expt (car x) 2)))
这是函数是编程,而
是命令式编程,结果一样,但思想不同。(defun imp (x) (let* ((y (car x)) (z (expt y 2))) (list 'a z)))
函数式编程还要尽量避免对函数的参数进行修改,避免所谓副作用(side effect),除了某些地方要利用它的情况除外。
C语言只能返回一个值,所以有时候要用指针或引用传递参数作为返回值;而lisp可以返回多个值
由底向上
bottom-up programming相对于自上而下、分治的编程风格,优点:利用clisp交互式的编程环境,可以写完一个模块就马上进行测试;一些实用函数(utility function)还可以在今后的项目中使用,随着写的程序越多,这些实用函数就越显出价值,你的工具越丰富,程序就越简洁紧凑,磨刀不误砍柴工。抽象
要写实用函数就需要培养抽象能力,发现相似程序共同的结构/pattern,比如经常要写类似这样的递归:求类表的长度
判断列表lst中所有元素是否都被fn函数判断为真:(defun len(lst) (if (null lst) 0 (+ 1 (len (cdr lst)))))
(defun all(fn lst) (if (null lst) t (and (funcall fn (car lst)) (all fn (cdr lst)))))
(其实clisp中以上这两个例子都已经有内置函数了,叫length和every)
它们结构相似,可以写一个更通用的函数来实现这种递归结构的函数的功能:
(defun rec(joiner end base) (labels ((inner-rec (lst) (if (null lst) (if (functionp end) (funcall end) end) (funcall joiner (if (functionp base)(funcall base (car lst)) base) (inner-rec (cdr lst)))))) #'inner-rec))
定义的函数rec的返回值也是一个函数,这个返回的函数拥有递归的结构,可以实现上面len和all两个例子的功能:
(setf all2 (rec #'(lambda(x y)(and x y)) t #'oddp)) (funcall all2 '(1 2 3));相当于(all #'oddp '(1 2 3)) (setf len2 (rec #'+ 0 1)) (funcall len2 '(1 2 3));相当于(len '(1 2 3)) (setf copy (rec #'cons nil #'identity));生成一个用于复制列表的函数copy (setf has-number (rec #'(lambda(x y)(or x y)) nil #'numberp));has-number判断列表是否含有数字 ...
think recursively
作者在书中大量使用递归,尽管有时效率并不高,他认为递归让代码优雅。第一遍先用递归写,代码完成后再尽量改成尾递归,这样编译器(应该说是reader)会把尾递归优化成效率较高的迭代
相关文章推荐
- 本以为GOOGLE会用XML来存放聊天记录
- [转]不要以为你是白领你就不是“三峡好人”——《三峡好人》影评
- 函数式编程让JS更优美
- 最近值得推荐的两篇文章《Map Reduce - the Free Lunch is not over?》以及《函数式编程另类指南》 [zz]
- 教养---那些自以为有个性的人,看看吧
- 本以为是民族骄傲,哪知道是外企渠道
- 函数式编程另类指南3
- 函数式编程的杂七杂八
- 我以为我够坚强
- 编程语言的发展趋势及未来方向(3):函数式编程(转)
- 函数式编程介绍之极简版
- 我靠。我一直以为的set方法是错的。。
- 编程思想基本概念之函数式编程(Functional Programming)
- 别总以为asp.net mvc比asp.net web form好--web form的页面也可以体积小巧
- 不要以为写写代码就是计算机科学
- 我以为
- 昨天遇到了linux 一个问题 以为是改hostname 的值 ,但是不是
- 函数式编程(一)
- 利用脚本将java回归到面向函数式编程
- javascript 函数式编程(1)