相比于其它函数式编程语言,Erlang 的优势在于它的并发程序设计与分布式程序设计。
并发是指一个程序中同时有多个线程在执行。例如,现代操作系统允许你同时使用文字处理、电子制表软件、邮件终端和打印任务。
在任意一个时刻,系统中每个处理单元(CPU)都只有一个线程(任务)在执行,但是可以通过以一定速率交替执行这些线程使得这些它们看上去像是在同时运行一样。Erlang 中创建多线程非常简单,而且很容易就可以实现这些线程之间的通信。Erlang 中,每个执行的线程都称之为一个 process(即进程,注意与操作系统中的进程概念不太一样)。
(注意:进程被用于没有共享数据的执行线程的场景。而线程(thread)则被用于共享数据的场景下。由于 Erlang 各执行线程之间不共享数据,所以我们一般将其称之为进程。)
Erlang 的内置函数 spawn 可以用来创建一个新的进程: spawn(Module, Exported_Function, List of Arguments)
。假设有如下这样一个模块:
-module(tut14). |
-export([start/0, say_something/2]). |
say_something(What, 0) -> |
done; |
say_something(What, Times) -> |
io:format("~p~n", [What]), |
say_something(What, Times - 1). |
start() -> |
spawn(tut14, say_something, [hello, 3]), |
spawn(tut14, say_something, [goodbye, 3]). |
5> c(tut14). |
{ok,tut14} |
6> tut14:say_something(hello, 3). |
hello |
hello |
hello |
done |
9> tut14:start(). |
hello |
goodbye |
<0.63.0> |
hello |
goodbye |
hello |
goodbye |
<0.63.0>
到底是哪儿来的呢?在 Erlang 系统中,一个函数的返回值是函数最后一个表达式的值,而 start 函数的第后一个表达式是:
spawn(tut14, say_something, [goodbye, 3]). |
<0.63.0>
也就是 spawn 返回的一个进程标识符。下面一个例子就可会讲解如何使用进程标识符。
另外,这个例子中 io:format
输出用的不是 ~w
而变成了 ~p
。引用用户手册的说法:“~p
与 ~w
一样都是将数据按标准语法的格式输出,但是当输出的内容需要占用多行时,~p
在分行处可以表现得更加智能。此外,它还会尝试检测出列表中的可输出字符串并将按字符串输出”。