- 💬 前言:本章我们要开始介绍如何使用 OCaml 进行函数式编程。书中探讨函数式编程的原因主要有三点。首先,我们将会设计和实现编程语言,而实现语言将会使用函数式编程语言OCaml,因为在实现编程语言的解释器 (interpreter) 或类型系统 (type system) 等处理程序作为数据的程序时,函数式语言非常方便。第二个原因是,包括OCaml在内的函数式语言从编程语言理论的角度来看是设计良好的语言。仅仅是研究这些语言的特征,就能对编程语言有很多了解。尤其是函数式编程的概念,近年来大多数编程语言都在借鉴,因此深入理解其他语言也必不可少。
-
📃 目录:
0x00 介绍 OCaml
在使用 Ocaml 编写程序先,我们需要了解一些基本的概念。
🔗 Ocaml 官网:Welcome to a World of OCaml
Objective Caml(OCaml)是 Caml 编程语言的主要实现,由 Xavier Leroy,Jérôme Vouillon,Damien Doligez,Didier Rémy及其他人于1996年创立。
OCaml 是开放原始码项目。此项目的管理和大部分维护工作交由 INRIA。由于 caml 的读音与camel一致,OCaml 的吉祥物自然被定为骆驼,而以 OCaml 服务为主的软件也通常以骆驼的形象作为其LOGO。 OCaml 将 Caml 语言在面向对象方面做了延展。Caml 是函数式编程语言,它的扩展语言还有基于微软.net平台的 F# 语言。
0x01 通过 REPL 执行 OCaml 程序
有三种主要方法可以执行 OCaml 程序,我们先来介绍第一种。
首先,使用文本编辑器编写程序并保存为名为 hello.ml
的文件,如下所示:
let _ = print_endline "Hello World"
这是一个使用标准输出函数 print_endline
来打印字符串 "Hello World" 的程序。
.
为了执行上述程序,首先可以使用 REPL (Read-Eval-Print Loop,交互式编程工具) 。
在命令行中输入 ocaml
,REPL 将会启动,会看到如下所示:
$ ocaml
OCaml version 4.09.0
#
此时如果按下回车键,字符串将被打印出来:
# print_endline "Hello World";;
Hello World
- : unit = ()
这里的 ; ; 是告诉 REPL 执行命令的符号,在将程序编写到文本文件时不需要使用它。
在 REPL 中,不仅可以直接输入程序,还可以读取存储在文件中的整个程序:
# #use "hello.ml";;
Hello World
- : unit = ()
0x02 使用 OCaml 解释器来执行程序
下面,我们来介绍第二种方式。使用 OCaml 解释器来执行程序。
只需在命令 ocaml
后面加上要执行的文件名即可:
$ ocaml hello.ml
Hello World
0x03 使用编译器 ocamic 来执行程序
在 Linux 环境中,也可以使用编译器 (ocamlc) 来创建和执行可执行文件:
$ ocamlc helloworld.ml
$ ls
a.out hello.cmi hello.cmo hello.ml
$ ./a.out
Hello World
编译后会生成一个名为 a.out 的可执行文件,运行该文件会输出字符串 "Hello World"。
0x04 函数式编程程序构成的基本单位:表达式
与 C, Java, Python 等命令式编程语言相比,OCaml 等函数式编程语言的最大特点是 ——
程序构成的基本单位不是语句 (statement),而是 表达式 (expression)。
.
通常在编程语言中,语句是指改变程序状态的句法结构。
例如,C 或 Java 中的赋值语句 x = x + 1 就是一个语句,它会将内存中存储的变量 x 的值增加 1。
而表达式是不改变程序状态的,仅通过计算产生一个值的句法结构。
例如,表达式 x + y 只是引用 x 和 y 的值来计算一个新值,并不会改变内存状态。
.
在函数式编程语言中,程序通常围绕表达式来编写,重点在于通过计算值而不改变内存状态。
由于函数式编程是围绕表达式来编写程序的,因此在函数式编程中,
与其说是注重解决问题的步骤,不如说是注重描述要解决的问题。
这种编程语言的选择对解决问题的思维方式有很大的影响,后面会结合实例进行更详细的探讨。
0x05 原始值和基本数据类型
OCaml 提供的最基本的表达式。
整数、浮点数、布尔、字符、字符串等 原始值 (primitive value) 的表达式。
例如,我们在 REPL 中输入算术表达式 :
# 1 + 2 * 3;;
- : int = 7
OCaml 执行器会计算输入的表达式,并告知结果为7,同时也会显示结果的类型(type)。
例如,int 表示结果为整数类型,可以如下计算浮点数表达式:
# 1.1 +. 2.2 *. 3.3;;
- : float = 8.36
上述式子的结果是 8.36,并且表示它是浮点类型。
OCaml 是一种根据数值类型明确分类值的语言。
甚至对于浮点数和整数的加法操作符也是不同的。
在上面的例子中,进行浮点数操作时,需要在操作符后面加上点号(.)。
如果没有明确分类数值的类型,就会导致类型错误 (Type error) :
# 3 + 2.0;;
Error: This expression has type float but an
expression was expected of type int
加法运算符 + 预期其操作数为整数值,但右操作数的值为浮点数,因此无法进行计算。
要将整数和浮点数相加,需要显式地进行类型转换,如下所示。
# 3 + (int_of_float 2.0);;
- : int = 5
# (float_of_int 3) +. 2.0;;
- : float = 5.
int_of_float 和 float_of_int 分别是将浮点数转换为整数和将整数转换为浮点数的函数。
.
布尔 (bool) 分别用 true 和 false 表示:
# true;;
- : bool = true
# false;;
- : bool = false
算术表达式的比较运算也会产生布尔值:
# 1 = 2;; (* equal to *)
- : bool = false
# 1 <> 2;; (* not equal to *)
- : bool = true
# 2 <= (1+1);; (* less than or equal to *)
- : bool = true
利用逻辑运算符可以将现有的布尔表达式连接起来,生成新的布尔表达式:
# (2 > 1) && (3 > 2 || 5 < 2);;
- : bool = true
# not (2 > 1);;
- : bool = false
除此之外,在 OCaml 中还提供了字符、字符串、和 unit 值作为基本类型:
# ’c’;;
- : char = ’c’
# "Objective " ^ "Caml";;
- : string = "Objective Caml"
# ();;
- : unit = ()
unit 是一种只包含一个值的类型,其值用 () 表示。这类似于 C 语言中 void 类型的作用。
在上面的例子中,^ 是连接两个字符串的操作符。
📌 [ 笔者 ] 王亦优
📃 [ 更新 ] 2024.6.24
❌ [ 勘误 ] /* 暂无 */
📜 [ 声明 ] 由于作者水平有限,本文有错误和不准确之处在所难免,
本人也很想知道这些错误,恳望读者批评指正!
📜 参考资料 - R. Neapolitan, Foundations of Algorithms (5th ed.), Jones & Bartlett, 2015. - T. Cormen《算法导论》(第三版),麻省理工学院出版社,2009年。 - T. Roughgarden, Algorithms Illuminated, Part 1~3, Soundlikeyourself Publishing, 2018. - J. Kleinberg&E. Tardos, Algorithm Design, Addison Wesley, 2005. - R. Sedgewick&K. Wayne,《算法》(第四版),Addison-Wesley,2011 - S. Dasgupta,《算法》,McGraw-Hill教育出版社,2006。 - S. Baase&A. Van Gelder, Computer Algorithms: 设计与分析简介》,Addison Wesley,2000。 - E. Horowitz,《C语言中的数据结构基础》,计算机科学出版社,1993 - S. Skiena, The Algorithm Design Manual (2nd ed.), Springer, 2008. - A. Aho, J. Hopcroft, and J. Ullman, Design and Analysis of Algorithms, Addison-Wesley, 1974. - M. Weiss, Data Structure and Algorithm Analysis in C (2nd ed.), Pearson, 1997. - A. Levitin, Introduction to the Design and Analysis of Algorithms, Addison Wesley, 2003. - A. Aho, J. Hopcroft, and J. Ullman, Data Structures and Algorithms, Addison-Wesley, 1983. - E. Horowitz, S. Sahni and S. Rajasekaran, Computer Algorithms/C++, Computer Science Press, 1997. - R. Sedgewick, Algorithms in C: 第1-4部分(第三版),Addison-Wesley,1998 - R. Sedgewick,《C语言中的算法》。第5部分(第3版),Addison-Wesley,2002 |