Erlang(六)顺序编程

apply

apply(Mod, Func, [Arg1, Arg2, ...])

回调模块mod的func,参数为arg(可以为元组)

内置函数的动态调用

apply(erlang, atom_to_list, [hello]).
"hello"

算术表达式

元数

元数是函数拥有的参数数量

名称相同,元数不同的函数是两个完全不同的函数。(注:类似多态?)

示例:将名称相同,元数不同的函数作为辅助函数,不导出辅助函数达到隐藏目的

sum(L) -> sum(L, 0).
sum([], N)    -> N;
sum([H|T], N) -> sum(T, H+N).

属性

-AtomTag定义文件的某些属性,预定义型、用户定义型 预定义型

-module(modname)

modname必须是一个原子,是文件的第一个属性。

自动代码加载,modname和文件名modname.erl一致。

-import(Mod,[Name1/Arity1,Name2/Arity2,...]).

列举了那些函数需要导入到模块中,导入后无需指定模块名

-export(Mod,[Name1/Arity1,Name2/Arity2,...]).

导出当前模块的函数,只有导出的函数才能在模块之外调用

-complie(Options).

添加Options到编辑器选项列表中]

-compile(export_all).

导出模块中的所有函数,不同-export显示导出

-vsn(version)

指定模块的版本号,用于分析程序或说明文档

用户定义的模块属性

-SomeTag(Value)

SomeTag是一个原子,Value是一个字面数据类型。模块属性的值会被编译进模块,可以在运行时获取。

-module(attrs).
-vsn(1234).
-author({joe,armstrong}).
-purpose("example of attributes").
-export([fac/1]).
fac(1) -> 1;
fac(N) -> N * fac(N-1).
attrs:module_info().
[{exports,[{fac,1},{module_info,0},{module_info,1}]},
{imports,[]},
{attributes,[{vsn,[1234]},
    {author,[{joe,armstrong}]},
    {purpose,"example of attributes"}]},
{compile,[{options,[]},
    {version,"4.8.2"},
    {time,{2015,4,6,2,56,18}},
    {source,"/mnt/hgfs/erlang/jaerlang2-code/code/attrs.erl"}]}]
beam_lib:chunks("attrs.beam",[attributes]).
{ok,{attrs,[{attributes,[{author,[{joe,armstrong}]},
    {purpose,"example of attributes"},
    {vsn,[1234]}]}]}}

可以在不载入模块代码的情况下提取模块里的属性

块表达式

begin
    ...
end

表达式序列,值为最后表达式的值

布尔值

布尔表达式

字符集

R16B之后默认UTF8

注释

%

%%可以被编辑器识别

10、动态代码载入

每当调用someModule:someFunciton(...)的时候,调用的总是最新模块里的最新版函数,代码在模块里重新编译了该模块也是如此。

a循环调用b时重新编译了b,下一次a调用b时就会自动调用新版b。

任意时刻,erlang运行一个模块的两个版本同时运行,当前版和旧版,重新编译某个模块时,旧版代码的进程终止,当前版变成旧版,新编译版本成为当前版。

Erlang预处理器

编译前有Erlang预处理处理,会展开源文件里所有宏,并插入必要的包含文件。

erlc -P someModule.erl

转义序列

可以再字符串和带引号的原子里使用转义序列来输入任何不可打印的字符。

表达式和表达式序列

可以执行并生成一个值的事物称为表达式。

表达式序列是一系列由逗号分隔的表达式。值为序列最后表达式的值。

函数引用

引用当前函数

localFunc/Arity

引用模块函数

Mod:Func/Arity

15、包含文件

-inclue(FileName).

包含文件的扩展名是.hrl

包含头文件可以使用下面语法:

-inclue_lib(Name).
-inclue_lib("kernel/include/file.hrl").

kernel是头文件的应用

头文件存放共享通用的记录定义

列表添加和移除操作符

++--用于列表添加和移除的中缀操作符。

-define (Constant, Replaement).

使用?Constant

预定义宏

-?FILE展开成当前文件名

-?MODULE当前模块名

-?LINE当前行号

宏控制流

取消宏定义

-undef(Macro).

定义过才执行

-ifdef(Macro).

没定义才执行

-ifudef(Macro).

用于ifdef和ifudef之后,否执行

-else

标记结束

-endif

模式的匹配操作符

fun1([{tag, {one,A}, B}|T]) ->
    ...
    ... f(..., {tag, {one,A}, B}, ...)
    ... g(..., {one,A}, ...)
    ...

fun1([{tag, {one,A}=Z1, B}] = Z2|T) ->
    ...
    ... f(..., Z2, ...)
    ... g(..., Z1, ...)
    ...

数字

整数

传统写法

K进制整数

$写法

浮点数

操作符优先级

进程字典

每一个Erlang进程都有一个被称为进程字典的私有数据存储区域。

进程字典一个关联数组,k-v格式。

key-value操作,无锁,哈希+数组排列方式,内容参与gcc,变量可变。

process dict破坏了fp的变量不可变语义。

内置操作:

put(Key, Val) -> term()
get() -> [{Key, Val}]
get(Key) -> Val | undefined
get_keys(Val) -> [Key]
erase() -> [{Key, Val}]
erase(Key) -> Val | undefined

引用

引用是一种全局唯一的erlang数据类型。

由内置函数,erlang:make_ref()创建,引用的用途是创建独一无二的标签。

短路布尔表达式

Exp1 orelse Exp2

Exp1为true,Exp2不会执行

Exp1 andalse Exp2

Exp1为true,Exp2会执行

在对应的A or B和A and B中,两边的参数总会被执行。

比较数据类型

number < atom < reference < fun < port < pid < tuple < record < map < list < binary

元组模块

下划线变量

_Var代表一个常规变量,而不是匿名变量。

一般来说,当某个变量在字句中只使用了一次,编译器会产生一个警告,通常是出错的信号。但是只用一次的下划线开头变量,就不会有错误产生。

用途:

1.命名一个不打算使用的变量,例如:open(File, _).

2.用于调试

erlang9