首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Erlang 编程简介,第 一 部分

2012-08-10 
Erlang 编程简介,第 1 部分?尽管这里只简要介绍了数据类型,但是我们希望让您对基本数据类型和操作有足够的

Erlang 编程简介,第 1 部分

?

尽管这里只简要介绍了数据类型,但是我们希望让您对基本数据类型和操作有足够的了解。

表达式和模式匹配

在研究数据类型时,我们已经看到了许多表达式和构造。表达式的重要元素是变量。Erlang 中的变量必须以大写字母开头,后面是大写字母、小写字母和下划线的任意组合(参见 清单 28)。


清单 28. Erlang 中的变量

41> Value = 99.99

?

在 Erlang 中,在对变量赋值时,是一次性将值绑定到变量。绑定变量之后,就不能改变它的值(参见 清单 29)。


清单 29. 将值绑定到变量

42> Value = 100.** exception error: no match of right hand side value 100

?

这与大多数语言不一样 — 变量的定义通常意味着值是可变的。在 Erlang 中,只能赋值一次意味着:如果希望向计算某个值的结果,则必须将它赋值给新的变量(参见 清单 30)。


清单 30. Erlang 中变量的限制

43> Sum = Value + 100199

?

只能赋值一次的好处是,在计算过程中很难意外地设置或改变变量值,这让值的识别和调试变得更容易,也让代码更为清晰,有时候更简短(因为可以简化结构)。

注意,这种操作意味着先计算出值,然后把值绑定到变量。在其他语言中,可以根据函数或操作的引用设置值,这意味着值取决于访问它时引用的值。在 Erlang 中,在创建变量时它的值总是已知的。

可以使用 f(Varname) 显式地忽略一个变量的绑定,或使用 f() 忽略所有变量的绑定。

为变量赋值实际上就是一种特殊的模式匹配。Erlang 中的模式匹配还会处理各个语句的执行流,以及从复合数据类型(元组、数组)中提取出值。模式匹配的基本形式是:模式 = 表达式。

表达式由数据结构、绑定的变量(即具有值的变量)、数学操作符和函数调用组成。操作的两边必须匹配(也就是说,如果模式是包含两个元素的元组,那么表达式的计算结果也必须是包含两个元素的元组)。在执行表达式时,计算表达式并将结果赋值给模式。

例如,可以使用一个模式匹配同时为两个变量赋值(参见 清单 31)。


清单 31. 同时给两个变量赋值

48> {A,B} = {(9+45),abc}.{54,abc}

?

注意,如果模式是绑定的变量,或者模式的元素是绑定的变量,那么模式匹配的结果就会变成比较。此操作支持实现强大的选择性赋值。例如,为了从元组中获取姓名和电子邮件地址,可以使用以下模式匹配:{contact, Name, Email} = {contact, "Me", "me@example.com"}

最后,可以按前面提到的构造表示方法,使用模式匹配从列表或元组中提取元素。例如,清单 32 展示了如何获得列表中的前两个元素,同时保留其余元素。


清单 32. 获得列表中的前两个元素,同时保留其余元素

53> [A,B|C] = [1,2,3,4,5,6].[1,2,3,4,5,6]

?

A 赋值为 1B 赋值为 2C 赋值为列表的其余部分。

函数

与其他语言一样,Erlang 中的函数是所有程序的基本组成部分。函数由函数名(由一个原子值定义)和圆括号中的零个或更多函数参数组成:sum(N,M) -> N+M

函数必须在文件中的模块中定义(不能在 shell 中定义函数)。参数可以包含复合数据类型。例如,可以使用元组中的标签选择不同的操作(参见 清单 33)。


清单 33. 可以使用元组中的标签选择不同的操作

mathexp({sum, N,M}) -> N+M ;mathexp({sub, N,M}) -> N-M ;mathexp({square, N}) -> N*N.

?

分号是每个函数定义之间的 “或” 操作符。使用模式匹配评估函数的参数,所以如果把包含三个元素的元组提供给 mathexp() 函数,模式匹配会失败。

Erlang 中的函数还可以接受不同数量的参数。Erlang 会执行模式匹配,直到找到有效的函数定义,从而选择适当的函数定义。函数的参数数量称为元数 (arity),用于帮助标识函数。

再看一下 Fibonacci 示例,现在您就会发现,当调用 fibo(0) 时,模式与函数的第一个定义匹配,fibo(1) 与第二个定义匹配,其他值与最后一个定义匹配。这也解释了函数执行的递归是如何实现的。例如,在调用 fibo(9) 时,可以使用相应的值调用 fibo(N) 函数定义,直到到达 fibo(0)fibo(1) 函数定义(它们返回固定的值)。

任何函数的返回值都是子句(在我们的示例中只有一行)中最后一个表达式的结果。注意,只有在找到了匹配项且变量是函数局部变量的情况下,才会为变量赋值。

模块

与其他语言中的模块一样,模块用于把相似的函数集中在一起。

在文件中指定模块名(必须与文件名匹配),然后指定模块中希望导出到装载此模块的其他程序的函数。例如,清单 34 给出了文件 fib.erl,其中包含 fib 模块的定义。


清单 34. fib.erl 文件

-module(fib).-export([fibo/1, printfibo/1]).%% print fibo arg. and result, with function as parameterprintfibo(N) -> Res = fib:fibo(N), io:fwrite("~w ~w~n", [N, Res]).fibo(0) -> 0 ; fibo(1) -> 1 ; fibo(N) when N > 0 -> fibo(N-1) + fibo(N-2) .

?

模块声明位于 -module() 行中。-export() 行包含要导出的函数的列表。每个函数的定义都给出了函数名和函数的元数,以便您能导出函数的特定定义。

要使用模块,则需要编译并装载模块。可以在 shell 中使用 c() 语句完成这个步骤,参见 清单 35。


清单 35. 使用 c() 语句编译并装载模块

1> c(fib).{ok,fib}2> fib:printfibo(9).9 34ok

?

注意,函数调用包含模块名,从而确保调用的是 fib 模块中的 printfibo() 函数。

结束语

Erlang 的结构和格式与大多数其他语言有很大区别。尽管许多数据类型和基本的表达式是相同的,但是它们的用法和应用不太一样。变量只能赋值一次,通过模式匹配系统对不同的表达式进行运算,这些特性给典型的语言环境提供了一些强大的扩展。例如,可以为同一函数定义多种处理方式,还可以对递归调用应用模式匹配,这样做可以简化某些函数。

在下一篇文章中,我们将讨论 Erlang 的进程、消息解析和网络功能,并通过研究 MochiWeb HTTP 服务器了解这种语言的强大功能和灵活性。

?

本文转载于developerWorks,原文在这里

热点排行