O‘Caml:新编程语言(之一)

来源:百度文库 编辑:神马文学网 时间:2024/04/29 22:19:57
说一门新外语,O‘Caml(之一)

文档选项

将此页作为电子邮件发送

拓展 Tomcat 应用

下载 IBM 开源 J2EE 应用服务器 WAS CE 新版本 V1.1
级别: 初级
赵蔚, 自由职业者
2002 年 7 月 01 日
本文介绍一个对大多数读者朋友来说,相信都相对比较新奇的编程语言,这就是 O‘Caml。这是在 Perl 之外,又一门以骆驼为吉祥物的编程语言。不过,O‘Caml 的骆驼可是很富有曼妙的诗意的啊。相信读者朋友们在经过了一番探索后,会明白这曼妙的诗意究竟是缘何而来。还有,据说,O‘Caml 可是真正挑剔的程序员的首选编程语言哦。
本文中,作者使用了台湾计算机作家侯捷先生倡导使用的一些翻译名词。比如,把 Type 翻译成"型别",而不是"类别",因为 Class 一次被翻译成"类",这样可以避免含糊;又比如,Function 翻译成"函式",而不是"函数";Argument 翻译成"引数",而不是"实参"等等。希望读者朋友们不会觉得"怪怪的"。说实话,作者还是比较赞同侯先生的。
为什么呢?不过,学习一门新的编程语言难道真的是很难吗?呵呵,也许真的是这样的吧。但是,对于我们这些程序员来说,学习一门新的编程语言可是一件很大开眼界的事情啊。而且,即使我们不想学习新的编程语言,新的编程语言也是蜂拥而来,真的是很没有办法的事情。不仅仅是像 C# 和 Java 这样通俗的新的编程语言,而且,读者朋友们经常可以在一些专用的场合,看到一门又一门的从没有见过的新的编程语言。学习一门新的编程语言的能力,可以说,已经成为一名程序员所必须的"生存"能力之一了。而培养这个能力的最好办法,难道不就是开始学习一门新的编程语言吗?
而且,学习一门新的编程语言,可以说,是开始探索计算机科学的庞杂知识体系的一条好路子。一门又一门的新的编程语言,从各自不同的角度,为我们打开计算机科学的一个又一个的新视界。只有通过编程语言,我们才可以和计算机进行交流。和计算机进行交流的这个唯一的渠道,难道不是最值得我们这些程序员的重视吗?




回页首
哈哈,那我再讲讲 O‘Caml 的"酷"吧。
首先,O‘Caml 不是像 Java 或者 C# 那样,是一门非常热门的不得了的编程语言。读者朋友们要问我了,难道这也算是优点不成?是啊,当然!"随大溜"难道是一流的程序员干的事情吗?
呵呵,认真的说,O‘Caml 还是非常的流行的,但是 O‘Caml 的流行是通过程序员的众口相传,而不是通过那些铺天盖地的广告。
其次,O‘Caml 宣称自己是给真正挑剔的程序员使用的。有些编程语言可不是这样哦,他们一开始就宣称自己是设计起来给"大路货"的程序员使用的。这实在是有伤自尊啊!那些真正好的编程语言,比如 C,Perl,Smalltalk,Lisp,都是设计者设计起来给自己用的编程语言。给自己用的!读者朋友们请想一想,就算设计者再高明,她或他明确的设计起来给"大路货"的程序员使用的编程语言,和大师们设计起来给自己用的编程语言相比较,恐怕是好不到哪里去的吧。
第三,O‘Caml 的动机很好,它是为了研究 Functional Programming 而设计起来的。而不是为了商业利益而产生的编程语言。第四,O‘Caml 有一个曼妙无比的骆驼做它的吉祥物。读者朋友们到 O‘Caml 的主页上去看看就知道了。第五,没有人强迫你使用 O‘Caml。你的老板只会强迫你使用,呵呵,你不喜欢的编程语言。




回页首
好啦,玩笑话说到这里,下面来讲讲 O‘Caml 到底是怎么一会事吧。O‘Caml 是面向对象的 Caml 语言。而 Caml 则是 ML 的一种法国方言。ML 还有其它的方言,最有名的可能要数 Lucent 公司旗下大名鼎鼎的贝尔试验室开发的 Standard ML of New Jersey,如果有机会,我们今后也可以介绍一下这个蛮有趣的 SML/NJ 的。话说回来,O‘Caml 是一种自动侦测型别(Type)的 Functional 编程语言。所谓 Functional 系列的编程语言,它们最重要的特征之一,就是用 Functional 编程语言写出来的程序几乎没有边界效应。
在 O‘Caml 中,一个例程,或者说一个函式(Function)是这个编程语言中所谓的第一等的公民。何谓"第一等(Fisrt Class)的公民"?就是说,在 O‘Caml 中,函式可以像一个 int 或者 float 一样被很方便的传递来传递去。这也就是所谓"Functional 编程语言"中,Functional 一词的由来。
O‘Caml 又有一个很强的型别系统。有多态(Polymorphic)和型别自动侦测(Type Inference)的功能。强的型别系统,配上型别自动侦测,这是 O‘Caml 区别于 Lisp 的很重要的一点。
模式匹配。对于习惯用 C 语言这一系列的编程语言的读者朋友们来说,模式匹配实在是一种稀奇古怪的编程方法。不过,用起来倒是很爽的说。说起来,这有点像一个过分增强了的 Case 语句。
支持 Exception 和自动内存管理。说到支持 Exception,读者朋友们要是了解 Lisp 特别是 Scheme 中的 Continuation 这个概念的话,会觉得和 Continuation 比起来,这一套不太过瘾。如果以后有机会,我也希望向大家介绍一下 Scheme 这个 Lisp 方言。有人宣称,这个 Continuation 概念是计算机科学中的一个最大的发明之一。不过,呵呵,我们还是先回到 O‘Caml 上来吧。至于自动内存管理,也就是所谓的垃圾收集,现在大家都司空见惯了。
哦,别忘了,O‘Caml 还有很强的面向对象的功能。毕竟,O‘Caml 中的那个"O"就是指的面向对象的支持嘛。
这些东东,我们会在后文一一展开,详细说明的,读者朋友们请不必太过着急。关于 O‘Caml 和其它编程语言之间进行的详细的比较,我们也会在这一系列文章快要结束的时候进行。好啦,这就正式开始我们的 O‘Caml 之旅吧。
哦,对了。O‘Caml 可以在 Linux 和 Windows 还有 Mac OS 9 以及 Mac OS X 上跑,是免费的开放源代码的自由软件。而且,O‘Caml 有一个非常令人满意的 Library。如果读者朋友们想要进行跨平台的开发的话,O‘Caml 是一个非常不错的选择。在我们往下进行之前,读者朋友们可以先去 O‘Caml 的主页上下载一个 O‘Caml 的环境。这样,我们下面讲起来的时候,读者朋友们可以在一边动手练习,学习起来也方便一些。




回页首
我们先来看一个求阶乘的小程序。注意,下面行首的"#"符号,是 O‘Caml 命令行环境的提示符。O‘Caml 当然也可以让你在文本编辑工具中写你的大部头程序,然后再编译运行。不过,我们现在为了学习起来方便,在 O‘Caml 的交互式的命令行环境下工作。
# let rec fact n = if n<2 then 1 else n*fact(n-1) ;; val fact : int -> int = #
上面我们定义了一个 fact 函式。注意看到,O‘Caml 用";;"终结一个语句。这一点作者也是不很感冒,但是";"在 O‘Caml 中另有妙用,所以也没有什么办法。著名的 Alan J. Perlis 说过,"Syntactic sugar causes cancer of the semicolon."这也是没有办法的事情,除非你用 Lisp,但是 Lisp 又有多得让人头晕目眩的圆括号。
话说回来,上面第一行 let rec 表示我们要声明一个递归函式,函式的名称为 fact,接受一个引数(Argument)记为 n。在"="之后,是函式的定义体,这是一个很简单的递归求阶乘的算法。上面第二行是 O‘Caml 在收到我们的语句后,返回给我们的提示内容。它说的是,一个从 int 到 int 的函式被申明了。当然了,因为"阶乘"就是拿一个 int 来,然后算出它的阶乘,当然还是一个 int,然后返回。这里就体现出 O‘Caml 的强型别系统,配上自动的型别侦测,不需要我们声明 n 和 fact 的型别,像在 C 语言中一样,O‘Caml 自己就可以侦测出所有的型别关系。
下面运行一下,我们来计算 8 的阶乘。
# fact 8 ;; - : int = 40320 #
接下来,我们来瞄一眼所谓的 Functional 编程,其妙处何在?
# let next x = x+1;; val next : int -> int = # let compose f g x = f(g(x));; val compose : (‘a -> ‘b) -> (‘c -> ‘a) -> ‘c -> ‘b = #
第一行,我们又定义了一个新的函式"next",它也是一个从 int 到 int 的函式,简单的加一而已。然后,我们定义了一个"复合算子",它有两个函式做引数,第三个引数我们暂且不去管它。其中,第一个函式是从型别 ‘a 到型别 ‘b,第二个函式是从型别 ‘c 到型别 ‘a。两个函式被 compose 复合后,成为一个由型别 ‘c 到型别 ‘b 的新的函式。至于 ‘a 和 ‘b 和 ‘c 具体到底是什么型别,我们的复合算子并不关心。这里就体现了 O‘Caml 的多态(Polymorphic)的特性。这里,由 compose 的定义,我们还看到 Functional 编程可真让人惊讶,它竟然可以把一个个函式像一个个 int 或者 float 那样基本的型别一样,随意的倒来倒去。可以接受一个函式做引数,也可以返回一个函式!(我们下面紧接着就要看到返回一个函式的例子。)
接下来再看。
# let weird = compose fact next;; val weird : int -> int = #
这里,"compose fact next",把 fact 函式和 next 函式复合成一个新的函式,命名为 weird。这个 weird 函式是怎么一会事呢?我们看到,它当然还是一个 int 到 int 的函式。其实这个 weird 函式就是把一个 int 先加一,然后再求阶乘。也就是先 next,再 fact。读者朋友们看到这里恐怕不免有些晕乎乎的。想不到读程序也能醉人!而且是这么短的程序!我们上面看到这个 compose 不是要接收三个引数 f、g 和 x 嘛,怎么我们这里就给它两个引数,它也能返回一个结果出来?别急,别急,这也是 Functional 编程的奇妙之处,我们在下面还要详细讲到。
简单说来,如果你给 compose 三个引数,它就返回一个 int。但是,如果你给它两个引数,它就变成还要再接受一个引数,然后才能返回一个 int。请看,它还要再接收一个引数,然后才能返回,这不就变成一个函式了嘛。这个技术有个名堂,叫做"Currying",是纪念逻辑学家 Haskell Curry 的。(我的妈,逻辑学家都跑出来了!)
先往下进行,我们来看看 weird 的运算结果吧。
# weird 7;; - : int = 40320 #
果然如此,(7+1)! = 8! = 40320。当然,你也可以一下子就给 compose 三个引数,那样的话,它一下子就返回一个 int 结果来了。
# compose fact next 7;; - : int = 40320 #
读者朋友们如果以前只接触过 C 这一系列的编程语言的话,看到这里,恐怕会是头晕的厉害,而且不免会有疑问,这么复杂的东西,到底有什么用,有什么好处啊?Stepanov(谁是 Stepanov,STL 之父是也。何谓 STL,啊,啊,您要学的东西还比较多啊!呵呵。),他在谈到 Java 的时候说过一段有趣的话,"... for the first time in my life programming in a new language did not bring me new insights."我们反过来看,如果读者朋友您现在看 O‘Caml 觉得头晕的话,这证明您正在学新的东西,而且这新的东西是如此的有趣,它能用短短的一个小程序就让您头晕!难道生活中还有比这更加有趣的事情吗?
呵呵,玩笑话放一边,我们在这一系列的文章进行到某一个阶段的时候,还是会具体的谈一谈 Functional 编程的利与弊的。不过现在我们才刚刚开始,谈这个话题还略嫌早了一些。上面说到的 STL,可以说是 C++ 中最让人心旷神怡的宝贝东东。而且,STL 也是让初学者浑身冒汗的宝贝东东。您看,即使您只在 C 系列的编程语言里面活动,也会遇到这样的事情,而且只有遇到这样的事情,才能让您的水平更上一层楼。我没说错吧?




回页首
今天就到这里吧。下一次我们将开始介绍 Functional 编程。呵呵,美妙新世界等着我们呢!




回页首
1 The O‘Caml Language Homepage,http://www.ocaml.org




回页首


赵蔚,自由职业者。专业从事 Linux 及 Open Source 的咨询业务。喜欢 Tori Amos,Alanis Morissette,Bjork,PJ Harvey 还有 Suzanne Vega。