Erlang 编程手册(第二部分,包括匹配和模块)
3 匹配 Pattern Matching
3.1 匹配 Pattern Matching
变量通过匹配机制进行对数据的绑定。匹配发生在函数的执行过程、case- receive- try-表达式和匹配操作符(=)表达式中。
在匹配中,左手边的“pattern模式”将于右手边的项进行匹配。如果匹配成功,则该未绑定变量变为已绑定状态。如果绑定失败,就发生一个运行时错误。
例子:
1> X.
** 1: variable 'X' is unbound **
2> X = 2.
2
3> X 1.
3
4> {X, Y} = {1, 2}.
** exited: {{badmatch,{1,2}},...} **
5> {X, Y} = {2, 3}.
{2,3}
6> Y.
3
4 模块Modules
4.1 模块语法Module Syntax
Erlang代码被模块分割为不同的部分。一个模块通常包含一组属性和函数声明,均以(.)结尾。例如:
-module(m). % module attribute
-export([fact/1]). % module attribute
fact(N) when N>0 -> % beginning of function declaration
N * fact(N-1); % |
fact(0) -> % |
1. % end of function declaration
4.2 模块属性Module Attributes
一个模块属性定义了该模块的特定信息。一个属性通常包含一个标记和对应的值。
-Tag(Value).
Tag必须是常量,这时Value必须是字符类型的项。
任何的模块属性都可以被设定。属性是存储在编译后的代码中的,并且能够被使用。例如,函数beam)lib:chunks/2。
这里有几个模块属性是预定义了含义的,一些包含了两个参数,但是用户定义的模块属性只能有一个参数。
4.2.1 预定义模块属性Pre-Defined Module Attributes
预定义的模块属性可以被之前的任何函数声明所替换。
-module(Module).
模块声明,定义该模块的名称。模块的名称必须是一个常量,应该与该模块所在的代码文件名相同。
该属性必须首先被定义,而且也是惟一一个被强制要求的属性。
-export(Functions).
暴露函数。指定在模块中的哪些函数被向外公开可见。Functions是一个列表[Name1/Arity1,...,NameN/ArityN],这里的NameI是一个常量,二ArityI应该是一个整数。
-import(Module,Functions).
导入函数。导入的函数可以被以本地函数一样的方式进行调用,这不需要使用模块名作为前缀。
Module,是一个常量,指定导入的模块,Funcations是一个类似于export的函数列表。
-compile(Options).
编译选项。Options,一个单一选项或者是一组选项,这些选项将被在编译的时候自动添加道编译选项中。
-vsn(Vsn).
模块版本。Vsn是一个字符项,可以通过beam_lib:version/1来读取。
如果该属性没有被指定,版本默认为该模块的校验和。
4.2.2 行为模块属性Behaviour Module Attribute
我们能够通过行为(Behaviour)指定某个模块为回调模块:
-behaviour(Behaviour).
Behaviour 是行为的名称,可能是某个用户自定义的行为或者某个OTP标准行为 gen_server, gen_fsm, gen_event 或者 supervisor。
拼写为 behavior 系统也是接受的。
4.2.3 宏和记录的定义Macro and Record Definitions
用来定义宏和记录的方式和模块的属性的语法是一样的:
-define(Macro,Replacement).
-record(Record,Fields).
宏和记录的定义可以存在于模块的任何地方,甚至在函数的声明中也可以。
4.2.4 文件包含File Inclusion
和模块的其他属性的使用一样:
-include(File).
-include_lib(File).
File, 一个字符串,应该指向一个真是存在的文件。被指向的文件的内容将被包含在声明include的地方。
包含文件一般用在记录和宏定义处,用来供多个模块共享。推荐对这些将被包含的文件使用.hrl作为后缀名。
File 可以使用一个路径组件$VAR开始,并且返回os:getenv(VAR),如果os:getenv(VAR)返回false,则$VAR为空。
例子:
-include("my_records.hrl").
-include("incdir/my_records.hrl").
-include("/home/user/proj/my_records.hrl").
-include("$PROJ_ROOT/my_records.hrl").
include_lib 和 include类似, 但是并不指向绝对文件,而忽视第一个路径组件被假设为一个应用的名称。例子:
-include_lib("kernel/include/file.hrl").
代码中使用了 code:lib_dir(kernel) 来寻在当前版本的kernel的目录,并且在这些子目录中寻找文件file.hrl。
4.2.5 文件和行的设置Setting File and Line
类似的,这里预定义了宏FILE和LINE:
-file(File, Line).
该属性被一些工具(例如Yecc)获取编译的相关信息和获取源文件的相关信息。
4.3 注释Comments
注释可以放置于模块的任何地方,除了字符串和引起的常量中。注释以“%”开始,但是不包含一个结尾符也是合法的。(在每个行的末尾会有一个空白字符)