第二章 Erlang_开始

2.1综述

       在每次的学习经历中,你将在通往Erlang mastery的路上经历很多的阶段。让我一起来回顾在本书中你将会经历的阶段。

   第一阶段:我不确定……

       作为一个新手,你将要学会怎样启动一个系统,在shell中运行命令,编译简单的代码,并且逐步熟悉Erlang。(Erlang是一种简单的语言,不会花费你很长的时间。)

       让我们开始开始更详细的解释。作为一个新手,你可以按以下的步骤进行:

l        保证在你的电脑上有Erlang的运行环境。

l        学习运行和结束Erlangshell

l        探索怎样将表达式输入shell,评估他们并且理解结果。

l        观察怎样创建和修改程序,并且可以使用你最喜欢的编辑器。

l        shell上尝试着编译和运行你自己的程序。

       第二阶段:我对Erlang很满意

       到现在为止,你将会有一种语言的工作知识。如果你遇到语言上的问题,你将会在第五章找到答案。较高级的设计在86页。

l        你将会学习更多shell的优点。你开始接触shell的时候,他将比我们要求他做的更多。(例如,你能够重新调回和编辑以前的语句。这些在6.5节,在Erlang mastery中的命令编辑,130页)。

l        你将开始学习库(称作Erlang系数)。我所写的大部分程序要用到以下五个系数,lists, io, file, dict, and gen_tcp;因此这五个参数在本书中将使用多次。

l        当你的程序再变的大些,你将需要学习自动编译和运行。这种选择的工具是make。我们将看到怎样通过nakefile来控制程序。这些在6.4.Makefile自动编译。127页。

l        更大的Erlang运行环境使用大规模的收集库,叫做OTP。在你逐步获得Erlang经验的同时,你将会发现熟悉OTP将会节约很多时间。毕竟,如果有人已经写好了你需要的函数,为什么要重新发明轮子呢?我们将了解主要的OTP行为,特别是gen_server。这些在16.2,开始了解gen_server,在301页。

l        Erlang的一个主要的用途是编写广播程序,所以现在开始体验。你可以开始第十章的例子,广播程序,在175页。你可以以任何想要的方式扩展。

       2.5阶段:我可以了解一些可选择的材料

   你第一次,并没有读过这本书的任一章节。

       和你以往所遇到的语言都不一样,Erlang是一个并发程序语言—这将会使他特别的适合编写广播程序和现代的多核和SMP电脑。大多数的Erlang程序在多核和SMP电脑上运行的更快。

       Erlang程序包括使用样式设计。我叫做COPconcurrency-oriented programming)。

       当你使用COP时,在他们的解决方案中,将错误分类并且识别固有的同步事件(natural concurrency)。这是有效地编写任何一个同步程序(concurrent)的第一步骤。

第三阶段:我是一个Erlang 专家

       到现在为止,你已经掌握了语言并且可以写出一些有用的发布的程序。但是要达到真正的掌握,你还需要学习许多。

ü        MnesiaErlang发布了包括了一个内置的高速复制数据库,叫做Mnesia。他原本是设计作为telecom应用的,在此性能和容错性是必不可少的。今天他被广泛应用于一个(nontelecom)领域。

ü        编码编写的接口使用另一种程序语言,并且使用链式的(linked-in)驱动。这些在12.4章,linked-in drivers 221页。

ü        充分使用OTP管理行为—建立(behaviors-building)树状图,start scripts(运行脚本)等。这些内容在第18章,Making a System with OTP ,335页。

ü        怎样在多核电脑上运行和最优化程序。这些内容在第20章,Programming Multicore CPUs,在367页。

 

最重要的一课:

       贯穿本书有一条规则你必须记住:程序设计是乐趣无穷的。并且我个人认为设计分布式程序,像是程序或者是及时的消息程序,会比传统的连续程序有更多的乐趣。在电脑上,你能做的是比较少的,但是在电脑网络上你能做的确是无限的。Erlang提供了一种环境给网络应用和搭建优质产品的系统。

       为了帮助你开始,在技术章节我混合了一些实际中的应用。你可以将这些应用作为你自己经验的开始点。学习他们、修改他们,部署他们在我还没有想到的领域,我将会很高兴看到这些。

2.2安装Erlang

       在你做一切之前,你必须保证你的系统有Erlang的应用程序。开始一个启动的命令,输入erl

$ erl

Erlang (BEAM) emulator version 5.5.2 [source] … [kernel-poll:false]

 

Eshell V5.5.2(abort with ^G)

1>

       Windows操作系统,erl指令只在以下的情况下工作:你安装了Erlang,并且改变了该程序的PACH系统变量。假设你在标准情况下安装了程序,你通过Start>All Programs>Erlang OTP 菜单触发了Erlang。在附录B396页,我将会描述我怎样操作Erlang来运行MinGWMSYS

       注意:有时,我将出示提示(这一小块提示ErlangBEAM… (关于^G)。如果你不希望系统报告错误,这些提示对你是非常有用的。但你看到这些提示时,请不用担心并且去想它是什么。除非是非常相关的,他们将不会在大多数例子中出现。

       如果你发现一个错误:erl是一个未知指令,你需要将Erlang安装盘放入到你的电脑中。这意味着你需要做出一个决定—你是否愿意提前建立两元发布(a prebuilt binary distribution),使用发布包(on OS X),从资源建立Erlang,或者使用Comprehensive Erlang Archive Network(CEAN)

 

binary发布

       Erlangbinary发布支持WindowsLinux系统。安装一个binary系统是有系统依赖性的。所以我们依次介绍。

 

Windows

       你将会在http://www.erlang.org/download.html 中找到解决方案。选择最新版本的入口,点击Windows binary—这是Windows下执行。点击链接,跟着以下的步骤。这是一个标准的Windows下安装,所以你不会有什么问题。

 

Linux

       Binary包为Debian-based系统存在。在Debian-based系统中,发布以下的指令:

>apt-get install erlang

 

Mac OS X系统中安装

       作为一个Mac的使用者,你可以使用MacPorts 系统安装一个prebuilt的版本,或者你可以从资源建立MacPorts。使用MacPorts会简单一些,并且他在过期后会处理升级。然而,当MacPortsErlang发布时,会稍微延后。在最初写这本书时,例如,ErlangMacPorts版本在现有版本之前,有过两次发布。由此,在下一章节,我建议你(bite the bullet不会翻译)且从资源安装Erlang。为了做这些,你需要保证你有安装开发工具。(你们是DVD盘,和你的电脑一起赠送)

 

从资源安装Erlang

       非传统的binary安装时从资源建立ErlangWindows系统下没有什么特别的优点因为每一个版本的发布都伴随着Windows二元化和所有的资源。但是在MacLinux平台,在新的Erlang发布和可用的binary安装包提供之间,将会有推迟。许多类似于Unix的操作系统,安装的提示是类似的:

       1.取得最新的Erlang资源。资源将会是一个文本,它的名字类似于otp_src_R11B-4.tar.gz(这个文件中包括第四次发布的Erlang版本11。)

       2. 解压缩、配置、编译,以及安装如下:

       $tar –xzf otp_src_R11B-4.tar.gz

       $cd otp_src_ R11B-4

       $./configure

       $make

       $sudo make install

       注意:在搭建系统之前,你可以选择./configure命令—help 来查看提供的功能。

      

USE CEAN

       CEAN尝试收集所有主要的Erlang应用程序在一起,并形成一个统一的安装程序。使用CEAN的优点是他不仅管理基本的Erlang系统,并且管理大量的使用Erlang书写的数据包。这就意味着能够保持你的基本Erlang是最新的,同时你一样可以保持你的安装包。

       CEAN为许多操作系统和处理器结构(processor architectures)提前编译了binaries。使用CEAN安装系统,请访问http://cean.process-one.net/download/,跟着步骤。(注意一些读者称CEAN不能安装Erlang编译器。如果你遇到同样的情况,请运行Erlangshell,并且输入以下的命令cean:install(compiler)。这样将会安装编译器。

2.3本书的代码

       我们展示的大部分代码都是完整的运行的例子,这些都可以下载。为了帮助你尽快的上手,本书出现的代码都能找到下载,将有提示的条目在代码上面。

下载 shop1.erl

-module(shop1).

-export([total/1]).

total([{What, N}|T]) ->shop:cost(What) * N + total(T);

total([]) -> 0.

 

       这个条目包括了代码下载时的路径。如果读到这本书的PDF版本,同时你的阅览器支持超链接,你可以直接点击。

2.4运行Shell

       现在我们开始。我们能与Erlang使用交互工具相互配合,叫做Shell。一旦我们运行Shell,我们写入表达式,然后Shell将运行他们的值。

       如果你已经安装了Erlang在你的系统上(如2.2节中介绍的,安装Erlang21页),然后ErlangShellerl将也被安装。为了运行它,打开一个传统的操作系统命令shellWindows上的命令或者一个shell像是基于Unix系统的bash)。在命令的驱动下,通过输入erl运行Erlang

$ erl

Erlang (BEAM) emulator version 5.5.1 [source] [async-threads:0] [hipe]

Eshell V5.5.1 (abort with ^G)

1> % I'm going to enter some expressions in the shell ..

1> 20 + 30.

50

2>

 

       看看我们刚才做的:

1. 这是使用Unix命令来运行ErlangshellShell用一个提示框来回应,你运行的Erlang是什么版本。

2.shell打印出提示1>,然后我们输入命令。%的符号表示命令的开始。所有的命令行都是从百分号开始的,同时被shellErlang得编译器忽略。

3.如果我们没有输入一个完整的命令,shell重复1>作为提示。在这一点上,我们输入20+30的表达式,紧接着有一个句号和(carriage)返回。(新手常常忘记输入句号。除了它,Erlang并不能知道我们表达式在那里结束,但是我们并不能看到显示的结果。)

4.shell评价表达式并且打印出结果(50,这种情况)。

5.shell打印出另外的提示,这是命令2(每次一旦输入新的命令,命令的数目将会增加)

      

       你是否在你的系统上运行shell?如果没有,请现在尝试。如果你刚刚阅读这份文档,但并没有运行命令。你可能想你已经理解发生了什么,但是你却不能将知识从你的大脑转化到你的手指——编程不是一个旁观者的运动。就像运动员一样,你必须练习。

       准确的输入例子中的表达式,随后体会它们,同时尝试着改变他们。如果不能运行,找出原因。体验Erlang程序在shell上的运行将会花费许多时间。

       当你获得更多的经验,你将会发现shell是一个强有力的工具。以往shell的命令可以重现(ctrl+Pctrl+N)和编辑(emacs-like 编辑命令)。这些在6.5节,在Erlangshell上编辑命令,130页。最好的,当你开始编写发布的程序,你将会发现:你可以将一个shell依附在一个运行的Erlang系统上,这个系统可能是在同一组的不同的Erlang节点上;或者系统可以将一个可靠的shell直接连接到一个远程的电脑的运行的Erlang系统上。

       警告:你不在shell中输入所有本书中的内容。尤其是,你不能输入Erlang程序文件中列出的代码。.erl文件中的句法格式并不是(shell中的)表达式,并且不能被shell解析。Shell只能解析Erlang表达式。尤其不要输入单元注解;这些注解在出现时将会有一连字符(像是-module-export等)。

       这一章的剩余部分就将会有一份Erlang shell的一组数据表格。我不能解释所有的细节,因为这将会打断文章的连贯性。第5.4章,不同的主题,在98页。我将会补充这些细节。

2.5简单的整数运算

让我们来计算下面的算术表达式:

1> 2 + 3 * 4.

14

2> (2 + 3) * 4.

20

      

       重点:你将会看到命令在命令数字1后出现(这是shell打印的,1>)。这意味着我们运行一个新的Erlang shell

 

 

Shell没有回应                                                                     

       如果输入一个命令而shell没有回应,这有可能是你忘记在命令的结尾输入句号通过格式返回(叫 做点-空白)。                                                                               

       另一种出错的原因可能是你试图输入一些东西,这些是被引用的(这些是,使用一个或者是两个  引用的记号),但同时没有输入一个相应的引用符,这个关闭的引用符和开始的引用符必须要是一致的。

       如果这些情况发生,最好的解决办法就是输入相应的关闭引用符。                           

       如果真的有了错误,然而系统却一点也没有回应,使用ctrl+CWindows上是ctrl+Break)。你将 会看到以下的输出内容:                                                                      

BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded                                       

               (v)ersion (k)ill (D)b-tables (d)istribution                                  

       这时仅仅需要点击A键得到现在的Erlang版本。                                            

高级的:你可以运行和停止许多的shell。在第6.7节,shell没有回应,在133页能找到细节。              

 

 

 

如果你想要准确的重现本书的例子,每次你看到一个由1>开始的对话框,你需要开始一个新的shell。当一个例子由提示的数字开始时候,并且这个数字大于1,这就意味着shell是从前面的例子延续下来的,所有你不需要开始新的shell

 

注意:当你读到这些文本,并你打算把这些例子输入到shell中(这是最好的学习方法)。同时你也许想要很快的看一眼第6.5章,在Erlang shell中命令的编辑。在130页。

       你将会看到Erlang的算术表达式是遵循一般的规则的,所以2+3*4意味着2+3*4)而不是(2+3*4

       Erlang使用任意长度(arbitrary-sized)的整数执行整形运算。在Erlang中,整形运算是精确的,所以你不用担心运算会超出负载或者是不能在一定字长表示一个整数。

变量标记法                                                                        

       我们常常讨论特殊的变量,正因为如此,我使用标记法 变量 |→值,所以,例如,A|42意思是变量A的值为42。有时有许多的值时,将这样写(A|42, B|true ...),意思是A42Btrue等。         

为什么不试一下?你能够给你的朋友这样的印象:你可以计算非常大的数:

3> 123456789 * 987654321 * 112233445566778899 * 998877665544332211.

13669560260321809985966198898925761696613427909935341

       你可以以这样的方式输入整数。这儿有一个表达式使用1632进制。

4> 16#cafe * 32#sugar.

1577682511434

2.6 变量

       你怎样存储命令的结果,所以你可以以后使用?这就是这些变量的用处。这是一个例子:

1> X = 123456789.

123456789

       这将会发生什么?首先,我们指定X变量的值;然后shell打印出这些变量的值。

注意:所有变量的值必须以大写字母开头。

       如果你想看到这些变量的值,只需要输入变量的名字:

2> X.

123456789

       现在变量X已经有一个值了,你可以使用它了:

3> X*X*X*X.

232305722798259244150093798251441

简单赋值就像代数                                                                                                                                                     

       以前我在学校,我的数学老师说,“如果有X在同一个表达式的不同位置,所有的X都有相同的值。”这就是我们怎么解方程式的关键:如果我们知道X+Y=10X-Y=2,在两个方程式中X6,同时Y4。  

       但是当我学习我的第一个程序语言,我们看到这样的东西;                                                                            

X = X+1                                                                                                                                                                         

       每一个人都这样说,“你不能这样!”但是老师说我们错了,我们必须忘记我们数学课上学到的东  西。X不是数学的变量:它像是一个鸽子洞或者小盒子…                                          

    Erlang中,变量和他们在数字中是类似的。当你给一个变量赋予一个值,你正在作出一个断言-一 个事实。这些变量有值。并且他们的值是这些。                                                 

 

 

然而,如果你想指定一个不同的值给变量X,你将会得到一个出错的消息:

4> X = 1234.

=ERROR REPORT==== 11-Sep-2006::20:32:49 ===

Error in process <0.31.0> with exit value:

       {{badmatch,1234},[{erl_eval,expr,3}]}

 

** exited: {{badmatch,1234},[{erl_eval,expr,3}]} **

 

       地球上的这儿正在发生着什么?为了解释这些,我打算分解两个假设,你必须有表达式X= 1234

l        首先,X不是一个变量,至少不是类似于JavaC语言之类的表达式。

l        第二,= 不是一个分配的操作符。

       这些可能是你新学习Erlang的技巧之一,所以我们花费两页来解释这些问题。

变量不再变化

       Erlang有一个单个的指定变量。同样建议,单个指定的值只能被指定一次。如果值已经被指定,而你却试图改变这个值,这将会出错(实际上,你将会看到匹配错误)。一个变量有一个指定的值,这叫做一个限制变量;另外,他被称为无限制变量。所有的变量无限制开始的。

       Erlang看到一个等式像是X=1234,他将变量X和值1234绑定在了一起。在绑定前,X可以是任意的值:他是一个空的洞,等待有值来填写。然而,一旦他得到一个值,他会一直保持这个值。

       在这一点上,你可能想知道为什么我们使用名称变量。有两个理由:

l        他们是变量,但是他们的值却只会变化一次(这就是,他们从无限制到拥有一个值)。

l        他们看起来像是变量在常规的程序语言,所以我们看到以这样开头的代码:

       X = ...

                     这时我们的大脑说,“我知道这是什么;X是一个变量,=是一个指        定的操作符。”并且我们的大脑几乎是正确的:X几乎是一个变量,并                     =几乎是一个指定的运算符。

              注意:在Erlang中,这种符号的使用()表示“我没有显示代码”。

      

       实际上,=是一个格式匹配运算符,它的行为像是指定X一个固定的值。

      

       最后,变量的范围是它定义的词汇单元。所以如果X被使用在一个单独的函数中间,它的值不能到函数之外。在同样的函数中,没有可共享的类似于全局和私有变量。如果X存在不同的函数中,所有的X都不一样。

 

类型匹配

       在许多的语言中,= 表示一个指定的等式。在Erlang中,然而,= 表示类型匹配操作符。Lhs = Rhs真正的意义是这样的:评估右边(Rhs),紧接着匹配左侧的结果的格式(Lhs)。

       现在,有一个变量,例如X,是一个典型的格式。让我们说的简单一点,变量只能赋一次值。第一次我们说X= 一些表达式,Erlang对他自己说,“我怎样做才能使表达式为真?”因为X还没有一个值,他可以把X的值绑定到一些值上,这些声明是有效的,每一个人都开心。

       然后,如果过一会X=另外的一个值,只有在现在的值和将要赋的值是一样才能使用。这是例子:

Line 1     1> X = (2+4).

        -    6

        -    2> Y = 10.

        -    10

        5   3> X = 6.

        -  6

        -  4> X = Y.

        -  =ERROR REPORT==== 27-Oct-2006::17:25:25 ===

        -   Error in process <0.32.0> with exit value:

       10         {{badmatch,10},[{erl_eval,expr,3}]}

        -   5> Y = 10.

        -    10

        -    6> Y = 4.

        -    =ERROR REPORT==== 27-Oct-2006::17:25:46 ===

       15  Error in process <0.37.0> with exit value:

        -           {{badmatch,4},[{erl_eval,expr,3}]}

        -    7> Y = X.

        -   =ERROR REPORT= = = = 27-Oct-2006::17:25:57 ===

        -    Error in process <0.40.0> with exit value:

        20       {{badmatch,6},[{erl_eval,expr,3}]}

 

       发生了什么:在第一行,系统计算表达式2+4,答案是6。所以在这行之后,shell有着接下来的结合:{X|>6}。第三行有一个估计,我们有这样的结合{ X|>6Y|>10}

       我们来看第五行,我在计算表达式前,我们知道X|>6,所以X=6匹配成功。

       第七行的X=Y,我们的绑定是{ X|>6Y|>10},同时系统打印出match信息以及错误的信息。

       表达式47中,成功或者是失败都取决于XY的值。现在正是时候认真观察的时候,并且确保你真的理解他们。

       在这一阶段,(I am belaboring the point)。所有的“=”的左边都是变量,无论是限制或者是不限制的,但是,我们将要看到的是,我们可以定义复杂的格式并且让他们与“=”来匹配。介绍完(tuple)和list后,我们将回到这个主题。

tuple)和list是用来存储合成的数据类型的。

 

为什么一个简单的赋值使我的程序更好?

       Erlang中,一个变量是一个值的引用——在Erlang的运行中,一个限制的变量值由一个指向存储区间的指针代表,这个存储空间内存着一些值,并且这个值不能改变。

       事实就是我们不能改变这个值,这一点非常重要。并且这一点与一些重要的语言像是C或者Java都不一样。

       我们可以看看当你试图改变这些值时,会发生什么。我们来定义变量X如下:

1> X = 23.

23

       我们在计算中使用它。

2> Y = 4 * X + 3.

95

       现在我们来改变X的值:

3> X = 19.

       幸运的是,Erlang不容许做这些。Shell编译喜欢并且说这些:

=ERROR REPORT==== 27-Oct-2006::13:36:24 ===

Error in process <0.31.0> with exit value:

       {{badmatch,19},[{erl_eval,expr,3}]}

 

       这就意味着但我们已经定义X23后,X不能成为19

       但是仅仅猜想我们能做到:的值将会是错误的,因为表达式已经不是一个等式了。此外,如果X可以在程序中的许多地方改变,将会有错误发生,很难说清楚哪一个X的值引发的错误,程序中的哪些地方又引用了这个错误的值。

       Erlang中,变量值在赋值之后不能改变。这些简化了调试。为了理解这些,我们可以问问我们自己错误是什么,怎样使错误可知。

       另一个常见的办法是:你发现你的程序出错是因为变量有一个未知的值。如果这就是程序错误的原因,你必须精确的找出陈旭在何处得到这个错误的值。如果这个变量在不同的地方改变了许多次,那么找出这个错误就很困难。

 

副作用的消除使我们的程序更加正常                                                                                   

       可以更改的存储领域中,它的技术术语在一种易变的状态。Erlang是一种功能程序语言,他有一种不易改变的状态。                                                                           

       在本书的后面,我们将看到怎样来编写多核CPU的程序。当它发生在多核CPU中,不易改变的状态是非常重要的。                                                                            

       如果你使用常规的程序,例如C或者是Java,来编写一个多核CPU的程序,然后你将不得不满足于共享内存所带来的问题。为了不破坏共享内存,当使用共享内存时,需要将它锁闭。当需要共享内存时,程序不能突然获得。                                                                         

    Erlang中,没有易变的状态,没有共享内存并且没有锁。这都是我们的程序更容易掌握。       

 

   在Erlang中,没有这样的麻烦。一个变量只能被赋一次值,并且不能被改变。所以我们一旦知道变量不正确,我们可以很快的定位出变量的范围。

    在这一点上,你可能在想怎样使编程抛弃变量变成可能。那你怎么表达类似于X= X+1的表达式?答案是简单的。重新定义一个新的表达式,他在以前没有使用过(假如是X1),写作X1=X+1

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值