ErLang中的标点符号 
ErLang语法中充满了一些约定。大写字母开头的名字(比如Address),表示一个变量,包括参数、局部变量等;小写字母开头的单词(比如ok),表示一个常量,叫做atom(原子的意思),包括常量名、函数名、模块名等。 
ErLang的注释用%开头。ErLang用下划线“_”表示任意变量,类似于Java的switch语法里面的default选项。 
ErLang脱胎于Prolog,不过,我觉得,ErLang语法和Haskell语法比较象,都是采用 -> 定义函数。 
ErLang语句中的标点符号用法很象文章的标点符号。 
整个函数定义结束用一个句号“.”;同一个函数中,并列的逻辑分支之间,用分号“;”分界;顺序语句之间,用逗号“,”分隔。 
ErLang中,{ }不是表示程序块的开头和结尾,而是表示一种特殊的数据结构类型——Tuple(元组),比如,{12, 3, ok}。我们可以把Tuple理解为定长数组。 
[ ] 则表示最基本的函数式编程的数据结构类型——List。List数据结构很基本,写法和用法也有一定的复杂度,不是表面上看起来那么简单,后面讲解Closure的章节会详细介绍List的最基本的构造原理。 
下面我们来看一个简单的例子。 
我们首先定义一个最简单的函数,把一个参数乘以10,然后加1。 
times10( Number ) –> 
Temp = 10 * Number, 
Temp + 1.

为了说明问题,上面的代码把乘法操作和加法操作分成两个步骤。Temp = 10 * Number语句后面是逗号,因为这是两条顺序执行的语句。 Temp + 1语句后面是句号,表示整个函数定义结束。而且,可以看出,ErLang没有return语句,最后执行的那条语句的执行结果就是返回 值。 
下面,我们把这个函数优化一下。当参数等于0的时候,直接返1;否则,就乘以10,然后加1,然后返回。这时候,我们就要用到case of逻辑分支语句,相当于java的switch语句。 
times10( Number ) –> 
case Number of 
0 -> 1; 
_ -> 
Temp = 10 * Number, 
Temp + 1 
end.

我们来仔细观察这段ErLang程序。 
当Number等于0的时候,直接返回1。由于这是一条分支语句,和后面的分支是并列的关系,所以,1的后面的标点符号是分号。后面这个分支,下划线“_”表示任何其它值,这里就表示除了1之外的任何其它数值。 
需要注意的一点是,case of语句需要用end结尾,end之前不需要有标点符号。 
上述代码中的case of 语句,其实就是Pattern Match的一种。ErLang的Pattern Match很强大,能够大幅度简化程序逻辑,后面进行专门介绍。 
Pattern Match 
Pattern Match主要有两个功能——比较分派和变量赋值。 
其中,比较分派是最主要的功能。比较分派的意思是,根据参数值进行条件分支的分派。可以把比较分派功能看作是一种类似于if, else等条件分支语句的简洁强大写法。 
上面的例子中,case Number of 就是根据Number的值进行比较分派。更常见的写法是,可以把Pattern Match部分提到函数定义分支的高度。于是,上述代码可以写成下面的形式: 
times10( 0 ) –> 1; 
times10( Number ) –> 
Temp = 10 * Number, 
Temp + 1.

这段代码由两个函数定义分支构成,由于两个函数分支的函数名相同,而且参数个数相同,而且两个函数定义分支之间采用分号“;”分隔,说明这是同一个函数的定义。函数式编程语言中,这种定义方式很常见,看起来形式很整齐,宛如数学公式。 
这段代码的含义是,当参数值等于0的时候,那么,程序走第一个函数定义分支(即分号“;”结尾的“times10( 0 ) –> 1;”),否则,走下面的函数定义分支(即“times10( Number ) –>…”)。 
第二个分支中的参数不是一个常数,而是一个变量Number,表示这个分支可以接受任何除了0之外的参数值,比如,1、2、12等等,这些值将赋给变量Number。 
因此,这个地方也体现了Pattern Match的第二个功能——变量赋值。

Pattern Match的形式可以很复杂,下面举几个典型的例子。 
(1)数据结构拆解赋值 
前面将到了ErLang语言有一种相当于定长数组的Tuple类型,我们可以很方便地根据元素的位置进行并行赋值。比如, 
{First, Second} = {1, 2} 
我们还可以对复合Tuple数据结构进行赋值,比如 
{A, {B, C}, D} = { 1, {2, 3}, 4 } 
List数据结构的赋值也是类似。由于List的写法和用法不是那么简单,三言两语也说不清楚,还徒增困扰,这里不再赘述。 
(2)assertEquals语句 
在Java等语言中,我们写单元测试的时候,会写一些assert语句,验证程序运行结果。这些assert语句通常是以API的方式提供,比如,assertTrue()、assertEquals()等。 
在ErLang中,可以用简单的语句达到类似于assertTrue()、assertEquals()等API的效果。 
比如,ErLang中,true = testA() 这样的语句表示testA的返回结果必须是true,否则就会抛出异常。这个用法很巧妙。这里解释一下。 
前面讲过,ErLang语法约定,小写字母开头的名字,都是常量名。这里的true自然也是一个常量,既然是常量,我们不可能对它赋值,那么true = testA()的意思就不是赋值,而是进行匹配比较。 
(3)匹配和赋值同时进行 
我们来看这样一段代码。 
case Result of 
{ok, Message} -> save(Message); 
{error, ErrorMessage} -> log(ErrorMessage) 
end.

这段代码中,Result是一个Tuple类型,包含两个元素,第一个元素表示成功(ok)或者失败(error),第二个元素表示具体的信息。 
可以看到,这两个条件分支中,同时出现了常量和变量。第一个条件分支中的ok是常量,Message是变量;第二个条件分支中的error是常量,ErrorMessage是变量。 
这两个条件分支都既有比较判断,也有变量赋值。首先,判断ResultTuple中的第一个元素和哪一个分支的第一个元素匹配,如果相配,那么把 ResultTuple中的第二个元素赋给这个分支的第二个变量元素。即,如果Result的第一个元素是ok,那么走第一个条件分支,并且把 Result的第二个元素赋给Message变量;如果Result的第二个元素是error,那么走第二个条件分支,并且把Result的第二个元素赋 给ErrorMessage变量。

在Java等语言中,实现上述的条件分支逻辑,则需要多写几条语句ErLang语法可以从形式上美化和简化逻辑分支分派复杂的程序。 
除了支持数相等比较,Pattern Match还可以进行范围比较、大小比较等,需要用到关键字when,不过用到when的情况,就比if else简洁不了多少,这里不再赘述。 
匿名函数 
ErLang允许在一个函数体内部定义另一个匿名函数,这是函数式编程的最基本的功能。这样,函数式语言才可以支持Closure。我们来看一个ErLang的匿名函数的例子。 
outer( C ) –> 
Inner = fun(A, B) -> A + B + C end, 
Inner(2, 3).

这段代码首先定义了一个命名函数outer,然后在outer函数内部定义了一个匿名函数。可以看到,这个匿名函数采用关键字fun来定义。前面讲过,函 数式编程的函数就相当于面向对象编程的类实例对象,匿名函数自然也是这样,也相当于类实例,我们可以把这个匿名函数赋给一个变量Inner,然后我们还可 以把这个变量当作函数来调用,比如,Inner(2, 3)。 
fun是ErLang用来定义匿名函数的关键字。这个关键字很重要。fun定义匿名函数的用法不是很复杂,和命名函数定义类似。
函数分支的定义也是类似,只是需要用end结尾,而不是用句号“.”结尾,而且fun只需要写一次,不需要向命名函数那样,每个分支都要写。比如, 
MyFunction = fun(0) -> 0; 
(Number) -> Number * 10 + 1 end, 
MyFunction(3), 
函数作为变量 
匿名函数可以当作对象赋给变量,命名函数同样也可以赋给变量。具体用法还是需要借助重要的fun关键字。比如, 
MyFunction = fun outer / 1

就可以把上述定义的outer函数赋给MyFunction变量。后面的 / 0表示这个outer函数只有一个参数。因为ErLang允许有多个同名函数的定义,只要参数个数不同,就是不同的函数。 
我们可以看到,任何函数都可以作为变量,也可以作为参数和返回值传来传去,这些变量也可以随时作为函数进行调用,于是就具有了一定的动态性。 
函数的动态调用 
ErLang有一个apply函数,可以动态调用某一个函数变量。 
基本用法是 apply( 函数变量,函数参数列表 )。比如,上面的MyFunciton函数变量,就可以这么调用,apply( MyFunction, [ 5 ])。 
那么我们能否根据一个字符串作为函数名获取一个函数变量呢?这样我们就可以根据一个字符串来动态调用某个函数了。 
ErLang中,做到这一点很简单。前面讲过,函数名一旦定义了,自然就固定了,这也类似于常量名,属于不可变的atom(原子)。所有的atom都可以 转换成字符串,也可以从字符串转换过来。ErLang中的字符串实质上都是List。字符串和atom之间的转换通过list_to_atom和 atom_to_list来转换。 
于是我们可以这样获取MyFunciton:MyFunction = list_to_atom(“outer”) 
如果outer函数已经定义,那么MyFucntion就等于outer函数,如果outer函数没有定义,那么list_to_atom(“outer”)会产生一个新的叫做outer的atom,MyFucntion就等于这个新产生的atom。 
如果需要强制产生一个已经存在的atom,那么我们需要调用list_to_existing_atom转换函数,这个函数不会产生新的atom,而是返回一个已经存在了的atom。 
Tuple作为数据成员集合 
前面讲解函数式编程特性的时候,提到了函数式编程没有面向对象编程的成员变量,这是一个限制。 
ErLang的Tuple类型可以一定程度克服这个限制。Tuple可以一定程度上担当容纳成员变量的职责。 
面向对象的类定义,其实就是一群数据和函数的集合,只是集合的成员之间都有一个this指针相关联,可以相互找到。 
ErLang的Tuple类型就是数据的集合,可以很自然地发挥成员变量的作用,比如,{Member1, Member2}。 
读者可能会说,ErLang的函数也可以作为变量,也可以放到Tuple里面,比如, { Memer1, Member2, Funtion1, Function2}。这不就和面向对象编程一样了吗? 
遗憾的是,这样做是得不偿失的。因为函数式编程没有面向对象的那种内在的this指针支持,自然也没有内在的多态和继承支持,硬把数据和函数糅合在一个Tuple里面,一点好处都没有,而且还丧失了函数作为实例对象的灵活性。 
所以,函数式编程的最佳实践(Best Practice)应该是:Tuple用来容纳成员数据,函数操作Tuple。Tuple定义和函数定义加在一 起,就构成了松散的数据结构,功能上类似于面向对象的类定义。Tuple + 函数的数据结构,具有多态的特性,因为函数本身能够作为变量替换;但是不具 有继承的特性,因为没有this指针的内在支持。 
正是因为Tuple在数据类型构造方面的重大作用,所以,ErLang专门引入了一种叫做Record的宏定义,可以对Tuple的数组下标位置命名。比 如,把第一个元素叫做Address,第二个元素叫做Zipcode,这样程序员就可以这些名字访问Tuple里面的元素,而不需要按照数组下标位置来访 问。 
Tuple和Record的具体用法还是有一定复杂度,限于篇幅,本章没有展开说明,只提了一些原理方面的要点。 
其它 
ErLang还有其它语法特性和细节,不再一一赘述。有兴趣的读者,可以自行去ErLang网站(www.erlang.org)进行研究。

erLang中的标点符号相关推荐

  1. Erlang中Eunit基本内容汇总

    Erlang中Eunit基本内容汇总 在你的module中添加: -include_lib("eunit/include/eunit.hrl"). 这样就引入了eunit的头文件, ...

  2. string对象中去掉标点符号

    C++ Primer 4th Edition,P78,习题3.10 题目要求:编写一个程序,从string对象中去掉标点符号.要求输入到程序的字符串必须必须包含标点符号,输出结果则是去掉标点符号后的s ...

  3. Erlang中一些错误或者异常的标识

    erlang中错误大体分为四种: 1. 编译错误     2. 逻辑错误     3. 运行时错误     4. 用户代码生成的错误 编译错误,主要是编译器检测出的代码语法错误  逻辑错误,是指程序没 ...

  4. 【Java】高效处理字符串中的标点符号

    [Java]清洗字符串中的标点符号 去除字符串中的所有标点符号 \pP 其中的小写 p 是 property 的意思,表示 Unicode 属性,用于 Unicode 正表达式的前缀. 大写 P 表示 ...

  5. WORD精灵:将Word文档中的标点符号统一为全角或者半角

    WORD精灵:将Word文档中的标点符号统一为全角或者半角 将Word文档中的标点符号统一为全角或者半角,比手工操作高效百倍

  6. 如何批量删除word中的中文和标点符号(word删除中文所有标点符号)

    如何批量删除word中的中文和标点符号(word删除中文所有标点符号) 当文档中前面一列英文,后面一列汉字的时候,你还在一个一个的去删除汉字吗?那样也太慢了.快快看看下面介绍的几种方法,绝对会大大提高 ...

  7. erlang 中#(井号)号的作用

    表示进制 10> 2#101010. %% 2 进制的 101010 42 11> 8#0677. %% 8 进制的 0677 447 12> 16#AE. %% 16 进制的 AE ...

  8. python不允许标点符号_python3去掉string中的标点符号方法

    网上看到的python去掉字符串中的标点符号的方法,大多是基于python2的,不适用python3,调整后代码如下: 代码 lower_case_documents = ['Hello, how a ...

  9. python并且符号_Python如何从文字中分离标点符号

    所以我想用空格将文本与标点符号分开.Python如何从文字中分离标点符号 my_text = "!where??and!!or$$then:)" 我想要有一个! where ?? ...

最新文章

  1. ServiceMesh有关sidecar理解
  2. JavaScript速记
  3. 0001242: Steps to make RealTek DVB-T USB dongle...
  4. A、B、C、D、E五人在某天夜里合伙去捕鱼,到第二天凌晨时都疲惫不堪
  5. 如何通过css控制内容显示顺序 第二行的内容优先显示
  6. 总结:第一章~第五章
  7. NetApp集群模式Data ONTAP展露新颜
  8. Spring 系统学习:Spring的事务管理---事务回顾
  9. 洛谷——P2084 进制转换
  10. CAD入门教程,基本设置,使用技巧
  11. js调用数科阅读器_多种方式实现JS调用后台方法进行数据交互
  12. javascript中正则匹配多个条件, 常用正则匹配, 正则详解
  13. (一)阿里云创建自己的产品和设备
  14. 利用文心大模型制作多功能机器人
  15. UG\NX二次开发 获取UG窗口句柄。实现操作UG窗口最小化、最大化、关闭功能
  16. Coin-row problem
  17. HTML5新特性之History
  18. 免杀学习——PHP免杀
  19. Maya动画1:基础知识小球弹跳
  20. 红领巾小创客机器人活动计划_争当红领巾小创客--小创客 大梦想

热门文章

  1. File System 定额(配额查询)
  2. 被final修饰的变量到底能不能被修改
  3. web程序安装说明书
  4. 《华为数据之道》-第7章 打造“数字孪生”的数据全量感知能力
  5. OpenGL中关于矩阵缩放、平移、旋转的讲解
  6. python html_在python中下载html?
  7. Java可以运行javac不能运行
  8. WPS word 如何取消定义网格线?无法修改行间距如何解决?
  9. 读书笔记系列--VB2005-菜根谭
  10. 最简单启动vue前端项目