普通的命令式语言是按照图灵机的模型建造的,因此就有了地址、指针之类的东东。
而一个具体的算法也就要受到这些简单的操作步骤的限制。
而函数式编程语言是按照递归论中的模型(lambda calculus)来建造的,因此抽象高了一个层次。
虽然这两个东西被证明是等价的,但是描述起算法来,fp会深入本质一点,而不必拘泥于如何优化底层机器数据的读写移动。
但是也往往因为如此,效率会比较低。
Take quick sort as an example,
用haskell 写的qs非常简单:
如果list 的长度小于1,则直接返回空list
否则,选取该list第一个元素作为pivot,
然后返回一个新的list,这个新的list由三部分组成。
第一部分是对一个list it的quicksort,it由原来的list中比pivot小的元素组成
第二部分是pivot
第三部分是对一个list st的quicksort,st由原来的list中大于等于pivot的元素组
于是quicksort就用递归简单地表达了出来。所以我们很容易地看出其递归的本质,以及解决问题的思想:divide and conquer。
然而每一步都要重新复制元素构造list it 与st,并返回新的list,可见效率不会好过手工写的C code。
因此以前也有过狂想,希望发明非冯诺依曼架构的LISP machine以符合其内部运行机理,以加快其速度,可惜理想与现实是有差距的。
花几年时间做出来的LISP machine,效率远远跟不上冯诺依曼机的速度发展,因此只好夭折了。
不过随着时间的发展,functional language越来越受重视,说不定某天,LISP machine就会出来了。
而一个具体的算法也就要受到这些简单的操作步骤的限制。
而函数式编程语言是按照递归论中的模型(lambda calculus)来建造的,因此抽象高了一个层次。
虽然这两个东西被证明是等价的,但是描述起算法来,fp会深入本质一点,而不必拘泥于如何优化底层机器数据的读写移动。
但是也往往因为如此,效率会比较低。
Take quick sort as an example,
用haskell 写的qs非常简单:
它的大概意思是:qsort [] = []
qsort (x:xs) = qsort lt ++ [x] ++ qsort st
where lt = [y | y <- xs, y < x]
st = [y | y <- xs, y >= x]
如果list 的长度小于1,则直接返回空list
否则,选取该list第一个元素作为pivot,
然后返回一个新的list,这个新的list由三部分组成。
第一部分是对一个list it的quicksort,it由原来的list中比pivot小的元素组成
第二部分是pivot
第三部分是对一个list st的quicksort,st由原来的list中大于等于pivot的元素组
于是quicksort就用递归简单地表达了出来。所以我们很容易地看出其递归的本质,以及解决问题的思想:divide and conquer。
然而每一步都要重新复制元素构造list it 与st,并返回新的list,可见效率不会好过手工写的C code。
因此以前也有过狂想,希望发明非冯诺依曼架构的LISP machine以符合其内部运行机理,以加快其速度,可惜理想与现实是有差距的。
花几年时间做出来的LISP machine,效率远远跟不上冯诺依曼机的速度发展,因此只好夭折了。
不过随着时间的发展,functional language越来越受重视,说不定某天,LISP machine就会出来了。
No comments:
Post a Comment