Erlang趣学指南(txt+pdf+epub+mobi电子书下载)


发布时间:2020-09-18 15:13:18

点击下载

作者:[加]弗莱德·赫伯特(Fred Hébert)

出版社:人民邮电出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

Erlang趣学指南

Erlang趣学指南试读:

前言

本书的写作最初是在网站上开始的,现在仍然能够访问http://learnyousomeerlang.com/(感谢No Starch出版社在出版和技术素材方面的完全开放性)。从2009年公开本书第1章的内容开始,本书慢慢地从一份只有3章内容的微型教程(当时在erlang-questions邮件列表中请求大家对内容进行校正)成长为一份学习Erlang的官方推荐文档、一本书、一个我生命中的重大成就。对于这本书带给我的一切,从朋友到工作,再到2012年度Erlang User的名号,我既困惑又感恩。致不了解Erlang的读者

当作为一个局外人从远处审视Erlang程序员时,会发现他们看起来像一个古怪的小团体,他们所信奉的原则几乎没有人愿意遵从。这些原则看起来不切实际、在应用方式上有诸多限制。更糟糕的是,Erlang社区的成员看起来很像某个宗教派别的成员,完全认为他们掌握了软件世界中心的唯一真理。这种“唯一真理”和Lisp派、Haskeller、形式化证明派中的自命不凡者、Smalltalk程序员、Forth中的栈派等语言狂热派以前所鼓吹的完全一样。没什么特别的,还是那老一套。它们都承诺一定会成功,只是方式不同,但是程序员所编写的程序仍然错误百出,仍然代价高昂,仍然难以维护。

对Erlang来说,可能是它对并发或者并行的承诺吸引读者阅读本书的。也许吸引读者的是这门语言对于分布式计算的支持,或者是其不寻常的容错机制。当然,带着怀疑来学习Erlang是一件好事。它不能解决你的所有问题——毕竟,这是你的责任。Erlang只是一个很好的工具箱,帮你解决问题。致Erlang熟手

你可能已经了解Erlang,或许还很深入。如果是这样的话,我希望本书阅读起来比较有趣,能够成为一本参考手册,或者其中的某些章可以让你更深入地了解Erlang语言的某些部分和工作环境,这些内容你以前可能不太熟悉。

也许,你对Erlang的了解在各个方面都比我好。那么,我希望本书能够拿来压压东西或者填充你的图书馆空间。致已经阅读过在线内容的读者

谢谢你的支持,本书的内容经过了专业的编辑,书中Erlang的版本也提升到了R15B+,希望你能喜欢。致谢

感谢Miran Lipovača首先想到了Learn You a Language这个主意,并同意我在本书以及相关的网站中借用这个想法。

感谢Jenn(我的女朋友)设计了最初的网站,为了能够让图片适合打印,她对本书中几乎全部图片进行了重新绘制,感谢她的辛苦工作。感谢她在我花费大量时间编写本书的过程中所给予的支持和耐心。

感谢所有花时间评审本书在线版本、寻找错误并提供帮助的人们(排名不分先后):Michael Richter、OJ Reeves、Dave Pawson、Robert Virding、Richard O’Keefe、Ulf Wiger、Lukas Larsson、Dale Harvey、Richard Carlsson、Nick Fitzgerald、Brendon Hogger、Geoff Cant、Andrew Thompson、Bartosz Fabianowski、Richard Jones、Tuncer Ayaz、William King、Mahesh Paolini-Subramanya以及Malcolm Matalka。还有很多其他人也做了少量的评审工作,指出了一些拼写等方面的错误。

还要再次感谢Geoff Cant,他是本书的正式技术评审。

感谢No Starch出版社的工作团队(Keith、Alison、Leigh、Riley、Jessica、Tyler和Bill)所做出的专业工作。

最后,感谢本书在线版本的所有读者,包括那些购买本书的读者和没有购买的读者。引言

这是本书的开头部分。阅读本书应该是学习Erlang编程的第一步,所以,我们还是有必要说点什么。

我是在读了Miran Lipovača的Learn You a Haskell for Great Good!(LYAH)教程后,才萌生了写这本书的想法。我觉得在引发读者兴趣和提供友好的学习体验方面,他做得非常棒。因为我早就认识他,我就去问他,如果我也按照这样的方式写一本关于Erlang的书,他会觉得怎样。他很喜欢这个想法,有部分原因应该是出于他对Erlang的兴趣吧。

于是我就开始写这本书。

当然,我之所以决定写这本书还有其他原因。当我开始学习Erlang时,我发现要找到这门语言的入门书很困难(Web上的文档稀缺,书又比较贵),并且我认为如果存在类似LYAH这样的指南,对整个Erlang社区都是有好处的。此外,我还发现人们对于Erlang好坏的评价都非常的笼统。

本书的读者需要具备命令式语言(像C/C++、Java、Python、Ruby之类)编程的基础知识,但是并不要求读者具备函数式编程语言(像Haskell、Scala、Clojure、OCaml和Erlang)方面的知识。我在编写本书时尽量做到客观、诚实,对Erlang实话实说,既肯定它的强项,也不避讳它的弱点。Erlang是什么

Erlang是一门函数式编程语言。如果你曾经用过命令式语言,那么像i++这样的语句对你来说再普通不过了,但是在函数式编程中,却不能这样使用。事实上,改变任何变量的值都是绝对不允许的。乍一听这似乎很奇怪,但是想想上过的数学课,你学到的内容是这样的:y = 2x = y + 3x = 2 + 3x = 5

如果我把以下内容加进去,你一定会觉得困惑。x = 5 + 1x = x∴ 5 = 6

函数式编程认识到了这一点。如果我说x是5,从逻辑上,我就不能说它也等于6!这属于欺诈。这也是为什么每次用同样的参数去调用函数时,它都应该返回相同的值:x = add_two_to(3) = 5∴ x = 5

对于同样的参数,函数永远要返回同样的值,这个概念称为引用透明性(referential transparency)。正是因为这一点,才能够把add_two_to(3)替换成 5, 因为3+2的结果就是5。这意味着,为了解决更为复杂的问题,我们可以将很多函数粘合在一起,还能保证不破坏任何逻辑。既合乎逻辑,又整洁,不是吗?不过还有一个问题:x = today() = 2013/10/22 -- 等待一天后 -- x = today() = 2013/10/23x = x∴ 2013/10/22 = 2013/10/23

哦不!我美丽的等式!它们突然间全部出错了!为什么我的函数每天返回的值都不同呢?

显然,在某些情况下,不遵循引用透明性是有用的。Erlang在函数式编程方面采用了一种非常注重实效的策略:遵守最纯粹的函数式编程原则(引用透明性、避免可变数据等),但是在遇到现实问题时,就打破这些原则。

Erlang是一门函数式编程语言,它同时也非常重视并发和高可靠性。为了让几十个任务能同时执行,Erlang采用了actor模型,每个actor都是虚拟机中的一个独立进程。简而言之,如果你是Erlang世界中的一个actor,你将会是一个孤独的人,独自坐在一个没有窗户的黑屋子里,在你的邮箱旁等待着消息。当你收到一条消息时,会用特定的方式来响应这条消息:收到账单就要进行支付;收到生日卡,就回一封感谢信;对于不理解的消息,就完全忽略。

可以把Erlang的actor模型想象成这样一个世界,其中每个人都独自坐在屋子里,可以执行一些不同的任务。人和人之间只能通过写信进行交流,就是这样。这样的生活虽然听起来很乏味(但却是邮政服务的新时代),但这意味着,你可以要求很多人为你分担不同的任务,他们做错了事或者犯了错误绝对不会对其他人的工作造成任何影响。除了你之外,他们甚至不知道还有其他人的存在(这真是太棒了)。

事实上,在Erlang中,只能创建出相互之间完全没有共享、只能通过消息通信的actor(进程)。每次消息交互都是显式的、可追踪的和安全的。

Erlang不仅仅是一门语言,同时也是一个完整的开发环境。代码被编译成字节码,字节码运行在虚拟机中。所以,Erlang很像Java,也像患有多动症的孩子,在任何地方都能运行。下面是Erlang标准发布中的一些组件:● 开发工具(编译器,调试器,性能分析器以及测试框架和可选的

类型分析器);● 开放电信平台(OTP)框架;● Web服务器;● 高级跟踪工具;● Mnesia数据库(一个键/值存储系统,能够在多台服务器上复制

数据,支持嵌套事务,并且可以存储任何类型的Erlang数据)。

Erlang虚拟机和库还能让用户在不中断任何程序的情况下升级运行系统的代码,能轻易地将代码分布在多台计算机上,还能用一种简单但强大的方式去管理错误和故障。

在本书中,我们会对其中绝大部分工具的使用方法进行介绍,也会讲解如何实现安全的系统。

谈到安全性,你应该知道Erlang中与之相关的一个总方针——任其崩溃(let it crash),这说的可不是一架崩溃后会导致大量乘客死亡的飞机,它指的更像是在下方铺有安全网络的钢丝上的行走者。尽管应该避免犯错,但是也不用时刻去检查每一种可能的错误情况。

Erlang提供了从错误中恢复的能力,用actor来组织代码的能力,以及用分布式和并发进行伸缩的能力,这些听起来都棒极了,那我们就赶快进入下一节吧……保持冷静

本书中有很多放入小框框中的文字都以这个名字为标题(阅读的过程中读者会看到)。Erlang目前之所以大受欢迎都源自于一些狂热的论点,这会导致人们对它过度信任。如果你也是一名狂热的Erlang学习者,那么下面的一些提醒有助于你保持清醒。

第一个提醒是,人们把Erlang强大的伸缩能力归结于它轻量的进程。没错,Erlang的进程的确非常轻量,你可以同时拥有数十万个进程。但是,这并不等于说,因为能这样用Erlang,所以一定要这样用。例如,在一个射击游戏中,让每颗子弹成为一个actor,就很不明智。要是按照这种方式设计一个射击游戏,能射中的就只能是自己的脚丫了。在actor之间发送消息还是存在少量开销的,如果把任务划分得太细,效率会降低不少!

在我们学到后面,真正需要关心这个问题时,我会深入进行讲解。现在只需记住,随意地对问题进行并行化是不足以提升其效率的。(别灰心,有时候,使用上百个进程既是可行的,也是管用的!)

也有观点说,Erlang的伸缩能力和计算机的核数成正比,但这通常不是真的。在某些情况下是可能的,但在绝大多数情况中,遇到的都是些无法让所有东西都同时运行的问题。

还有一件事情需要牢记,尽管Erlang在某些方面做得确实不错,但是,从技术上来说,用其他语言也是可能取得同样效果的。反之亦然。你应该仔细评估需要解决的问题,为其选择最佳工具和解决方案。Erlang不是银弹,尤其不适合开发图像和信号处理、操作系统设备驱动之类的功能。Erlang的强项在于:服务器端的大型软件(如队列中间件、Web服务器、实时竞价系统和分布式数据库),协助其他语言完成一些困难的工作,高层协议实现等。至于中间地带的部分,你自行决定。

Erlang也不是一定只能用来进行服务器端软件的开发。已经有人将Erlang用在很多意想不到的地方。一个例子就是IANO,它是Unict团队(Catania大学的Eurobot团队)制造的一个机器人,其中的人工智能部分就是用Erlang开发的。在2009年度Eurobot大赛中,IANO获得了银奖。还有一个例子是Wings 3D,这是一个开源、跨平台的3D建模工具(不是3D渲染器),也是用Erlang实现的。准备工作

学习Erlang,只要一个文本编辑器和Erlang环境就足够了。可以从Erlang官网上获取源码和Windows平台的二进制可执行文件。

对于Windows操作系统来说,下载并运行二进制文件即可。别忘了把你的Erlang目录添加到PATH系统变量中去,这样就能从命令行直接访问它了。

对于基于Debian发布的Linux操作系统来说,要用下面的命令来安装Erlang包:$ sudo apt-get install erlang

如果使用的是Fedora系统(假设已经安装了yum),可以输入下面的命令来安装Erlang:# yum install erlang

不过,这些库中存放的通常都是些陈旧的Erlang安装包。使用旧的版本运行本书中的样例代码可能会得到和书中不一样的结果,对有些特定的应用,还可能会出现性能下降。因此,我建议从源代码中编译出安装包。参考包中的README文件,并且使用Google查找需要的所有安装细节。

在FreeBSD中,有很多可用的选项。如果用的是portmaster,可以用下面的命令:$ portmaster lang/erlang

如果是标准的ports系统,可以输入下面的命令:$ cd /usr/ports/lang/erlang; make install clean

最后,如果想使用这个包,输入以下命令:$ run pkg_add -rv erlang

如果用的是Mac OS X系统,可以用Homebrew来安装Erlang:$ brew install erlang

如果喜欢的话,也可以用MacPorts:$ port install erlang注意 在撰写本书时,我使用的Erlang版本是R15B+,所以为获取最佳学习效果,读者应该使用这个版本或者更新的版本。不过,本书的绝大部分内容对像R13B这样老的版本也是有效的。

除了下载、安装Erlang外,读者还应当下载和本书配套的完整代码文件。其中包含有本书所有的程序和模块代码,都已经过测试。这些代码有助于修正读者自己程序中的问题。如果读者想跳着阅读本书,那么也可以把它们当作学习后面章节的基础代码。这些文件全部被打包放在一个zip包中,可以从http://learnyousomeerlang.com/static/erlang/learn-you-some-erlang.zip下载。除此之外,本书的样例代码不再有任何其他外部依赖了。从哪里寻求帮助

如果用的是Linux,就可以从man中找到很好的技术文档。例如,Erlang中有个lists模块(会在第1章中介绍)。要找到lists模块的文档,只需要输入以下命令:$ erl -man lists

在Windows系统中,安装得到的文件中包括HTML文档。也可以随时从Erlang官网或其他的备选网站上下载这些文档。

如果希望把代码写得整洁些,可以从http://www.erlang.se/doc/programming_rules.shtml中学些到一些优秀的编码实践。本书中的代码也会尽量遵循这些指导原则。

有时,读者会发现仅仅了解一些技术细节并不足以解决手边的问题。此时,我主要从两个地方寻求帮助:Erlang的官方邮件列表(跟着它,就能学到不少东西)和irc.freenode.net网站上的#erlang频道。第1章 启程

使用Erlang语言,可以在仿真器(emulator)中对绝大多数代码进行测试。在代码脚本被编译和部署后,不仅可以在仿真器中运行它们,还可以现场对它们进行修改。

在本章中,我们会介绍Erlang shell的使用方式,还会介绍一些基本的Erlang数据类型。1.1 使用Erlang shell

要在Linux或者Mac OS X系统上启动Erlang shell,首先需要打开一个终端,输入erl。如果之前已经正确安装了Erlang,就会看到如下显示:$ erlErlang R15B (erts-5.9) [source] [64-bit] [smp:4:4] [async-threads:0] [hipe][kernel-poll:false]Eshell V5.9 (abort with ^G)

祝贺,你成功运行了Erlang shell!

如果你是Windows用户,那么可以在命令行提示符中执行erl.exe启动Erlang shell,但是一般建议使用werl.exe,它存在于开始菜单中(选择All Programs → Erlang)。werl是一个专门用于Windows系统的Erlang shell,它有自己的窗口,窗口具有滚动条,还支持一些行编辑快捷键(Windows系统中的标准cmd.exe shell不支持这些快捷键)。然而,如果想重定向标准输入或者输出,又或者想使用管道,那么就只能使用erl.exe来启动shell。

现在,我们可以在shell中输入代码,并在仿真器中运行它们。但是,我们先要熟悉一下Erlang shell。1.1.1 输入shell命令

Erlang shell中内置了一个基于Emacs的功能子集构建的行编辑器,Emacs是一款流行的文本编辑器,从20世纪70年代使用至今。如果你熟悉Emacs,那就再好不过了。即便你对Emacs一无所知,也无妨。

首先,在Erlang shell中输入一些文本,然后,按下Ctrl+A(^A)。光标会移至该行的开头。同样地,按下Ctrl+E(^E),光标会移至该行的末尾。你还可以使用左右箭头键让光标前后移动,用上下箭头键在之前写好的代码行之间来回切换。

我们来试一些其他输入。输入li,然后按下Tab键。shell会自动把刚才输入的li自动补全为lists:。再次按下Tab键,shell中会列举出lists模块下所有可用的函数信息。你可能会觉得这种表示法比较奇怪,不过放心,很快你就会熟悉了(第2章会对模块进行更多的介绍)。1.1.2 退出shell

至此,Elang shell的大部分基本功能特性都已经介绍过了,除了一件非常重要的事情:我们还不知道如何退出shell呢!还好,有一种快速的寻求帮助的方法:在shell中输入help().并按下Enter键。你会看到一系列命令的相关信息,包括进程查看函数、shell工作方式控制函数等。其中大部分的命令都会在本书中用到,不过现在,我们最感兴趣的是下面这行描述:q() -- quit - shorthand for init:stop()

嗯,这是退出shell的一种方法(实际上,一共有两种)。但是,当shell被冻结住时,是无法输入这条命令的!

如果刚才启动shell时,你留意观察过,可能会看到一句“aborting with ^G.”字样的注解。那就按下Ctrl+G,然后再输入h寻求帮助。User switch command--> hc [nn] - connect to jobi [nn] - interrupt jobk [nn] - kill jobj - list all jobss [shell] - start local shellr [node [shell]] - start remote shellq - quit erlang? | h - this message-->

如果你还带着单片眼镜,是时候扔掉它了!和其他语言中的简单shell完全不同,Erlang shell是一组shell实例,每个实例运行着不同的作业(job)。此外,你可以像管理操作系统中的进程一样管理这些shell实例。如果输入k N,N是作业编号,就会终止掉承担这个作业的shell以及它运行的所有代码。如果不想杀死shell,只想停止shell中运行的代码,可以使用i N命令。你还可以输入s创建一个新的shell实例,用j列举出所有的shell实例,以及用c N来连上一个shell实例。

尝试这些命令时,你可能会看到某个shell作业旁有个星号(*):--> j1* {shell,start,[init]}

*表明这个shell是你最近一次使用的shell实例。如果在使用命令c、i或者k时,后面不带任何数字,那么命令会默认作用到这个最近使用的shell实例上。

如果shell冻结住了,一个快捷的解冻指令序列是:按下Ctrl+G、输入i、按下Enter键、输入c、按下Enter键(^G i ENTER c ENTER)。这个指令序列会先进入shell管理界面,中断当前shell作业,然后再重新建立连接。Eshell V5.9 (abort with ^G)1> "OH NO THIS SHELL IS UNRESPONSIVE!!! *hits ctrl+G*"User switch command --> i --> c** exception exit: killed1> "YESS!"

在向shell中输入有“实际意义”的内容之前,有件重要的事情要说明一下:表达式序列必须要以点号结尾,后面是空白符(换行符、空格之类),否则,表达式不会被执行。你可以用逗号来分隔表达式,但是只会显示最后一个表达式的执行结果(其他表达式也都执行了)。大多数人都会觉得这个语法很奇怪,这是因为Erlang最初是直接在Prolog中实现的。Prolog是一门逻辑编程语言。

现在,我们来做一些实践。就从学习Erlang的基本数据类型以及如何在shell中写一点Erlang程序开始吧。1.2 Erlang基础知识

虽然你刚刚看到的管理不同作业和shell会话的机制非常高级,但是Erlang仍然被认为是一门相对小巧、简单的语言(这里简单的含义与C比C++简单中的含义相同)。Erlang语言中只有少量内置的数据类型(相关的语法也不多)。我们先来看看数值类型。1.2.1 数值类型

按照前面讲过的方法,打开Erlang shell,并输入如下内容:1> 2 + 15.172> 49 * 100.49003> 1892 - 1472.4204> 5 / 2.2.5

可以看到,Erlang并不关心输入的是浮点数还是整数。算术运算对两种类型都支持。

注意,如果你希望整数除法演算的结果还是整数,而不是浮点数,必须要使用div。要获取整数除法的余数(模),可以使用rem(remainder,余数)。5> 5 div 2.26> 5 rem 2.1

在一个表达式中,可以使用多个操作符,算术计算遵循标准的优先级规则:7> (50 * 100) – 4999.18> -(50 * 100 – 4999).-19> -50 * (100 – 4999).244950

如果想以其他不为10的基数表示整数,只需以Base#Value这种形式输入数值即可(Base必须在2到36之间),像这样:10> 2#101010.4211> 8#0677.44712> 16#AE.174

在上面的例子中,我们把二进制数、八进制数、十六进制数转换成十进制数。太棒了!虽然语法有些奇怪,但是Erlang的计算能力完全可以和桌面角落里摆放的计算器媲美。真令人兴奋!1.2.2 不变的变量

能做算术运算固然不错,但是如果不能保存计算结果的话,也没多大用处。你可以使用变量来存放结果。如果读过本书的引言部分,应该知道在函数式编程中,变量是不会变化的。

在Erlang中,变量必须以大写字符开始。下面的6个表达式展示了变量的基本用法:1> One.* 1: variable 'One' is unbound2> One = 1.13> Un = Uno = One = 1.14> Two = One + One.25> Two = 2.26> Two = Two + 1.** exception error: no match of right hand side value 3

从这些命令的执行中,我们首先看出的是,一个变量只能被赋值一次。之后,可以“假装”给一个变量再赋一次值,只要这个值和变量已有的值完全一样。如果这两个值不同,Erlang会报错。现象是这样,但是解释要略微复杂一些,和=操作符有关。负责比较操作并且在不相等时报错的是=操作符(不是变量)。如果相同,Erlang会返回这个值:7> 47 = 45 + 2.478> 47 = 45 + 3.** exception error: no match of right hand side value 48

如果等号两边都是变量,并且左边是个未绑定的变量(没有任何值和它关联),Erlang会自动把右边变量的值绑定到左边的变量上。这样,两个变量就有了相同的值。因此,两边的值比较,肯定相等,并且左边的变量会一直把这个值保存在内存中。

下面是另外一个例子:9> two = 2.** exception error: no match of right hand side value 2

这个命令失败了,因为单词two是以小写字符起始的。注意 严格来说,变量名还可以以下划线(_)起始,但是依照惯例,这种变量仅用于不想关心其值的情况。

=操作符的这种行为表现是模式匹配(pattern matching)的基础,许多函数式编程语言中都有这个特性,只是通常认为,Erlang中的模式匹配要比其他语言中的更灵活、更完备。在本章的后面介绍其他数据类型时,我会更详细地介绍模式匹配。在后续的几章中,也会看到如何在函数中使用模式匹配。

注意,在shell中做测试时,如果不小心给某个变量赋错了值,可以使用f(Variable).函数把这个变量“删除”。如果想清除所有的变量,可以使用f().。这两个函数是专门用来辅助代码实验的,只能在shell中使用。当编写真实程序时,是不能用这种方法来销毁值的。如果你考虑到Erlang要适用于工业场景,就会觉得这个限制是合理的。一个shell极有可能不间断地运行很多年,在这期间某个给定变量名肯定会被重复使用。1.2.3 原子

变量名不能以小写字符开头有一个原因:原子(atom)。原子是字面量,这意味着原子是常量,唯一的值就是自己的名字。换句话说,你看到的就是你能得到的——别想得到更多。原子cat代表“cat”,就这样。你不能操作它、不能改变它、也不能把它分成几部分。它就是cat。只能接受它。

以小写字符开头的单词只是原子的一种写法,还有其他写法:1> atom.atom2> atoms_rule.atoms_rule3> atoms_rule@erlang.atoms_rule@erlang4> 'Atoms can be cheated!'.'Atoms can be cheated!'5> atom = 'atom'.atom

如果原子不以小写字符开头或者其中包含有除字母、数字、下划线以及@符号之外的其他字符,那么必须被放到两个单引号(')之间。第5行表明,原子加上单引号后和原来的原子相等。

我把原子比作名字,就是其值的常量。你以前编写过的代码中可能用过常量。例如,假设你用一些值来表示眼睛的颜色:1代表蓝色(blue),2代表棕色(brown),3代表绿色(green),4代表其他(other)。这些常量的名字必须要和底层的值进行匹配。但是,原子能够让你无须考虑那些底层的值。眼睛的颜色就是蓝色、棕色、绿色和其他。这些颜色可以用在代码的任何地方。底层的值绝对不会冲突,这种常量也绝不会出现没有定义的情况!(在第2章中,我们会介绍具有关联值的常量)。

因此,原子主要用来表达或者修饰和其放置在一起的数据,通常是在一个元组(tuple)(在1.2.5节进行介绍)中。有时(并不常见),单独使用原子也是有意义的。这也是为什么我们没有在此花过多篇幅介绍它的原因。在后面的例子中,会看到原子和其他类型数据的联合使用。保持冷静 在消息发送和常量表示方面,原子确实是个不错的选择。然而,在其他许多方面,使用原子会带来一些问题。每个原子都会被引用到一个原子表中,原子表会消耗内存(在32位系统中,每个原子需要4字节;在64位系统中,每个原子需要8字节)。原子表不被垃圾回收,所以原子会一直累积,直到系统因为内存耗尽或者创建的原子个数超过了1 048 577而发生崩溃。这意味着不能动态创建原子。如果系统需要可靠保证,但是用户输入部分动态创建了原子,那你就遇上大麻烦了,因为只要让其不停地创建原子就可以随意让系统崩溃。原子应该被当作开发者使用的工具,坦白说,它本来就是用作此目的的。再重申一遍:日常编码中,只要原子都是你亲手输入的,那么完全可以安全地使用它们。只有动态生成原子才会存在风险。注意 有些原子是保留字,这些原子不能使用,因为Erlang语言的设计者已经在一些特定的函数名、操作符、表达式等中使用了它们。这些保留字是after、and、andalso、band、begin、bnot、bor、bsl、bsr、 bxor、case、catch、cond、div、end、fun、if、let、not、 of、or、orelse、query、receive、rem、try、when和xor。1.2.4 布尔代数和比较操作符

如果无法区分出大小或者真假,那就有大麻烦了。和其他语言一样,Erlang也有布尔操作和比较操作。

布尔代数非常简单:1> true and false.false2> false or true.true3> true xor false.true4> not false.true5> not (true and true).false注意 布尔操作符and和or对操作符两边的参数都会去求值。如果你想要的是一个短路操作符(只在有必要时,才去求值右边的参数),可以使用andalso和orelse。

相等性测试和不等性测试也很简单,只不过使用的符号和其他语言中稍微有些不同:6> 5 =:= 5.true7> 1 =:= 0.false8> 1 =/= 0.true9> 5 =:= 5.0.false10> 5 == 5.0.true11> 5 /= 5.0.false

在其他常见的语言中,通常使用==和!=来做相等性和不等性比较,但在Erlang中,使用的是=:=和=/=。最后3个表达式(第9~11行)展示了一个陷阱:在做算术计算时,Erlang并不区分浮点数和整数,但是在做比较时,却会区分。不过别担心,如果你不想区分,可以使用==和/=操作符。因此,关键在于要想清楚是否需要精确的相等性。根据经验,你应该始终都用=:=和=/=,只有在明确知道确实不需要精确相等性时才换成==和/=。当数值的期望类型和实际类型不一致时,这种做法有助于避免一些错误的比较。

还有其他一些用于比较的操作符:<(小于)、>(大于)、>=(大于等于)和=<(小于等于)。最后一个是倒着写的(我的观点),我的代码中的许多语法错误都是由它产生的。请多留意一下这个=<。12> 1 < 2.true13> 1 < 1.false14> 1 >= 1.true15> 1 =< 1.true

如果输入5 + llama或者5 =:= true会怎样呢?要想知道答案,最好的办法当然是去试验一下,然后被错误结果吓一跳!12> 5 + llama. ** exception error: bad argument in an arithmetic expression in operator +/2 called as 5 + llama

看来,Erlang确实不喜欢我们将它的基本类型用错。仿真器返回一条出错消息,表明它不喜欢出现在+操作符两边的某个参数。

不过,对于用错类型,Erlang也并不总是会生气:13> 5 =:= true.false

为什么在有些操作中拒绝接受不同的类型,而在另一些操作中却又允许呢?尽管Erlang不允许把两个不同类型的操作数加在一起,但是却允许对它们进行比较。这是因为Erlang语言的发明者把实用性的优先级排在理论前面,觉得如果能简单地写出像通用排序算法那样的程序,可以对任意数据排序,岂不是很棒!做出这个决定是为了简化编程工作,事实也基本上证实了这一点。

在进行布尔代数和比较操作时,还有最后一点要铭记在心:14> 0 == false.false15> 1 < false.true

如果你原来熟悉的是过程式语言或者流行的面向对象语言,那么很可能要抓狂了。第14行应当求值为true,而第15行应当求值为false!毕竟,false代表0,而true代表除0以外的任何东西!在Erlang中不是这样。因为我对你撒了谎。是的,我确实撒谎了。很惭愧。

Erlang中并没有布尔值true和false之类的东西。数据项true和false都是原子,只要你始终认为false和true只能表示字面意思,那么它们其实和语言融合得是非常好的,不会带来问题。注意比较操作中,数据类型之间的大小顺序是:number < atom < reference < fun < port < pid < tuple < list < bit string。其中有些类型你现在可能还不熟悉,随着对本书的学习,你会逐渐了解的。现在,只需要记住,正是因为有了这个顺序,才可以在任意数据类型之间进行比较。引用Erlang语言的发明者之一Joe Armstrong的一句话:“具体的顺序并不重要——重要是定义明确的全局顺序。”1.2.5 元组

使用元组可以把一组数据项组织到一起。在Erlang中,元组的书写形式为{Element1, Element2

, ..., ElementN}。例如,如果你想告诉我笛卡儿坐标系中一个点的位置,就可以提供出它的坐标(x, y)。这个点可以被表示成一个具有两个数据项的元组:1> X = 10, Y = 4.42> Point = {X,Y}.{10,4}

在这个例子中,一个点就是两个数据项。这样,就不用到哪儿都带着变量X和Y,只要带着这一个元组就可以了。不过,如果拿到一个点,但是只想知道它的x坐标时,该怎么办呢?获取这个信息也没什么困难的。记住,在给变量赋值时,如果新旧值相同,Erlang就不会报错。

我们来利用这个特性。(在输入下面的例子前,需要用f()清除以前设置的变量。)3> Point = {4,5}.

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载