Lich Ray写了个帖子《
函数式编程语言曲高和寡?》, 用快速排序的例子来说明函数式编程在表达思想方面比命令式语言更容易,其实这一点毋庸置疑,如果你正在读或者读过SICP的话。文中给了haskell、 scheme和javascript的实现例子,我也凑趣写了个Erlang版本,haskell我不了解就不说了,其他实现分别如下:
scheme:
ruby 代码
- (define (qsort ls)
- (if (null? ls) '()
- (let
- ((x (car ls))
- (xs (cdr ls)))
- (let
- ((lt (filter (lambda (y) (< y x)) xs))
- (st (filter (lambda (y) (>= y x)) xs)))
- (append (qsort lt) (list x) (qsort st))))))
javascript:
js 代码
-
- Array.prototype.head = function () {
- return this[0];
- }
-
- Array.prototype.tail = function () {
- return this.slice(1);
- }
-
- Array.prototype.filter = function (proc) {
- var tmpArr = [];
- for (var i = 0; i < this.length; i++)
- if (proc(this[i]) == true)
- tmpArr.push(this[i]);
- return tmpArr;
- }
- Array.prototype.qsort = function () {
- if (this == false) return []
- var x, xs, lt, st
- x = this.head()
- xs = this.tail()
- lt = xs.filter(function (y) {return y < x})
- st = xs.filter(function (y) {return y >= x})
- return lt.qsort().concat([x], st.qsort())
- }
用Erlang的话,Erlang的list其实跟scheme的list是一样的,甚至连定义的基本高阶函数都一样:map,filter,append等等,利用lists模块提供的filter和append,我们可以写出:
ruby 代码
- qsort([])->[];
- qsort([H|T])->
- Lt=lists:filter(fun(E)->Eend,T),
- St=lists:filter(fun(E)->E>=H end,T),
- lists:append(qsort(Lt),lists:append([H],qsort(St))).
我们来比较下scheme和Erlang版本,两者最显著的不同是,scheme使用了条件语句if,而Erlang却是通过模式匹配来代替条件分支判 断。同样,在list的分解上面,Erlang也是利用了规则匹配来代替car,cdr函数,从这里可以看出规则匹配在Erlang中的主要作用:分解复 杂数据结构以便赋值和条件分支的分派。
扯远些可以谈到模式匹配是以“like-a”来代替消息分派在传统命令式语言中严格的“is-a”,这也跟现实世界的情况更为符合,现实世界中我们对事物 的判断都是模糊。而这一点,不正是“Duck-Typing”?传统语言对于对象的类型(type)判断来源于严格确定对象是什么类(class),不是 这个类它就没有相应的方法,而事实上类与类型这两个概念并不是一致的,对象的类型更应该根据对象能够做什么来决定。这只是我读《失踪的链环》 得来的感受,如果对模式匹配还有怀疑的话,让我们回到这个例子的Erlang版本,代码中我们调用了两次filter进行全表扫描,以便得到根据H切割的 大小两个部分,这在性能上有不小的影响,那么我们能不能只进行一次全表扫描呢,返回结果是“大小”两个部分,看看Erlang应该怎么写:
ruby 代码
- sort([]) -> [];
- sort([Pivot|Rest]) ->
- {Smaller, Bigger} = split(Pivot, Rest),
- lists:append(sort(Smaller), [Pivot|sort(Bigger)]).
- split(Pivot, L) ->
- split(Pivot, L, [], []).
- split(Pivot, [], Smaller, Bigger) ->
- {Smaller,Bigger};
- split(Pivot, [H|T], Smaller, Bigger) when H < Pivot ->
- split(Pivot, T, [H|Smaller], Bigger);
- split(Pivot, [H|T], Smaller, Bigger) when H >= Pivot ->
- split(Pivot, T, Smaller, [H|Bigger]).
这几行代码充分展现了模式匹配的威力,不过Erlang其实有内置的方法partition用于切割list的,这里只是为了展现模式匹配,因此上面的代码可以改为:
ruby 代码
- sort([]) -> [];
- sort([Pivot|Rest]) ->
- {Smaller, Bigger} = lists:partition(fun(E)->Eend, Rest),
- lists:append(sort(Smaller), [Pivot|sort(Bigger)]).
同样的代码改写为ruby版本:
ruby 代码
- def qsort(arr)
- if arr==[]
- []
- else
- x=arr.shift
- smaller,bigger=arr.partition{|e| e<=x}
- qsort(smaller)+[x]+qsort(bigger)
- end
- end
ruby与Erlang都有并行赋值,但是ruby不支持模式匹配。请注意ruby并没有尾递归优化,因此上面的代码在数组比较大的时候会导致栈溢出,想用ruby做函数式编程应该尽量多使用循环和map,filter,collect等辅助高阶函数。
另外一个Erlang与ruby、scheme比较重要的区别是Erlang的变量只能赋值一次(或者说绑定),也就是single assignment。这个特点与Erlang所要满足的运行场景有紧密关系,当系统发生错误时,就可以从原来的值重新启动任务,而不用担心由于变量值的 变化导致系统恢复困难。
分享到:
相关推荐
3. **ErlyJS**: ErlyJS是一个纯Erlang实现的JavaScript编译器,它面向Erlang VM,旨在提供高性能的服务器端JavaScript,简化Ajax和Comet Web应用的开发。ErlyJS可以与CouchDB的JSON API无缝对接。 【代码层面的结合...
Scheme例子.js
Scheme-Lib是一个专门为Scheme编程语言设计的库,特别针对Android平台进行了优化和适配。Scheme是一种历史悠久、功能强大的Lisp方言,以其简洁的语法和强大的函数式编程特性著称。在Android平台上使用Scheme-Lib,...
scheme语言structure数据类型的使用例子,使用方法参阅我的博文http://blog.csdn.net/tumiz/article/details/27852349
在移动应用开发中,"scheme"是一种常见的机制,用于实现应用程序间的交互,即从一个应用启动另一个应用。本文将深入探讨scheme如何实现唤醒外部APP,以及它在Webview和浏览器环境中的应用。 首先,理解scheme的基本...
GoScheme是一个用Go语言实现的Scheme编程语言解释器。Scheme是一种基于Lisp家族的函数式编程语言,以其简洁的语法和强大的元编程能力而受到程序员的欢迎。Go语言则以其高效的性能、简单清晰的语法以及良好的并发支持...
当一个应用希望监听并响应特定scheme的意图(Intent)时,需要在manifest中声明一个,并设置类别(action)为"android.intent.action.VIEW",数据类型(data)为自定义的scheme。例如: ```xml ...
### Scheme语言介绍与计算机科学基础 #### 一、标题与描述概述 - **标题**:“Learn Scheme” - **描述**:“Lisp is a perfect language....希望这份文档能为你开启探索Scheme之旅提供一个良好的起点。
1. **变燃烧能力**:`burnerreversingandvariationalburningcapacity.scm`可能是一个Scheme脚本,用于根据特定条件(如炉内温度或时间)改变燃烧器的燃烧能力,模拟实际操作中的不稳定性。 2. **控制逻辑**:Scheme...
- **交互式评估器**:Scheme拥有一个交互式的评估环境,可以即时测试代码的效果,非常适合学习和调试。 - **教育和研究领域的应用**:自1975年以来,Scheme就被广泛应用于教育和研究领域,尤其是在计算机科学的教学...
"rubeme"项目是一个在Ruby中实现的Scheme方言,Scheme是Lisp家族的一种编程语言,以其高度的表达性和简洁的语法结构闻名。这个项目展示了Ruby语言的灵活性,以及如何利用它的特性来构建一个完整的解释器或编译器。 ...
在iOS和Android等操作系统中,开发者可以利用URL Scheme实现应用间的深度链接,从而创建丰富的用户体验,比如从一个应用内直接打开另一个应用的功能。 在iOS开发中,URL Scheme的注册通常在Info.plist文件中进行,...
手机中的APP都有一个沙盒,APP就是一个信息孤岛,相互是不可以进行通信的。但是iOS的APP可以注册自己的URL Scheme,URL Scheme是为方便app之间互相调用而设计的。我们可以通过系统的OpenURL来打开该app,并可以传递...
15. 引擎:引擎是Scheme中的一个高级概念,用于创建和管理独立的执行线程。本书介绍了不同类型的引擎,包括时钟引擎、平面引擎和可嵌套引擎。 16. Shell脚本:Scheme可以用来编写Shell脚本。本书提供了编写简单的...
在Android开发中,`android:scheme` 是一个关键的概念,用于构建自定义URL协议,使得外部应用或系统可以通过特定的URI来启动我们的应用程序中的特定Activity。这个特性在很多场景下非常有用,比如分享链接、广告点击...
一个Scheme程序可以由一个或多个form组成,通常用小括号括起来。例如: ```scheme (define x 123) (+ 1 2) (* 4 5 6) (display "hello world") ``` 这些form可以是表达式、变量定义或过程。 **Form嵌套:** Scheme...
Sublime Text是一个流行的文本和源代码编辑器,拥有大量的插件和扩展,支持多种编程语言的语法高亮和代码片段。 《The Scheme Programming Language》书籍内容涵盖了Scheme语言的核心概念和高级特性,比如以下主题...
- **Guile**:Guile是GNU项目的组成部分之一,是一个基于Scheme语言的扩展语言库。它不仅可以作为一个独立的语言环境,还可以被集成到其他应用程序中作为脚本语言使用。Guile支持跨平台使用,可以在Linux和多种Unix...
Fluent Scheme 是一种基于 Scheme 语言的编程环境,旨在提供一个高效、灵活的解决方案 для scientific computing 和数据分析。以下是 Fluent Scheme 中文手册修订的知识点摘要: 1. Fluent Scheme 简介 Fluent ...