二进制型
即以大小号和255位内数字组成的数据流,可以把任何内置数据压缩为bit,也可以再解压出来。此外假如二进制型能用文字显示则会显示文字.此外二进制型的位数是8的倍数,否则就是位串类型
<<5,6,8>>
<<"abc">>
压缩io列表
对于元素是255内数字组成的列表,可以通过函数将其压缩成一维的二进制数据
test()->
list_to_binary([<<5,3>>,5,6,<<7>>]).
//<<5,3,5,6,7>>
切割二进制
test()->
split_binary(<<5,6,7,8,9,12>>,3).
//{<<5,6,7>>,<<"\b\t\f">>}
对数据进行编码解码
test()->
Student = {tang,55},
Key=term_to_binary(Student),
//<<131,104,2,100,0,4,116,97,110,103,97,55>>
byte_size(Key),//12
binary_to_term(Key).//{tang,55}
使用位语法打包及拆包RGB颜色
test()->
R = 2,
G = 61,
B = 22,
RGB = <<R:5,G:6,B:5>>,//<<23,182>>
<<R2:5,G2:6,B2:5>>=RGB,
R2,//2
G2,//61
B2.//22
位运算的后缀表达式
有四种表达式:
<<Value>>
<<Value:Size>>
<<Value/TypeSpecifierList>>
<<Value:Size/TypeSpecifierList>>
位运算允许在前面临时获得的Size在后面直接拿来声明长度。
<<Size:4,Data:Size/binary>> = Ceshi
位运算的类型指定列表
采用End-Sign-Type-Unit的格式,其中任意项都可以被省略,会使用默认值
End是字节顺序有big、little、native,默认big。big为高位优先、little则是低位优先,native是按照机器的顺序。最好的办法是用term_to_binary和binary_to_term来进行转码。
Sign是模式匹配,有singned、unsigned,默认unsigned。
Type是数据类型,有integer、float、binary、bytes、bitstring、bits、utf8、utf16、utf32,默认为integer
Unit写法为unit:1|2|..256,integer、float、bitstring的默认值为1,binary是8,而utf系列没有unit。字段长度为unit长度乘以Size。
匹配消息头
is_head(<<2#11111111111:11,B:2,C:2>>)->
case B of
0 -> {2,5};
1 -> exit(badVsn);
2 -> 2;
3 -> 1
end,
case C of
0 -> exit(badLayer);
1 -> 3;
2 -> 2;
3 -> 1
end.
通过2进则的十一个1来匹配消息头,就能很清楚的找到其是不是正确的头部,假如匹配失败则可以在调用的时候用try来处理不是时候的操作
ps:用file:read_file可以读取文件为二进制型
位推导
和列表推导类似,但是是针对位的操作,可以生成列表或者二进制型
test()->
Key = <<16#5d>>,
[ X || <<X:1>> <= Key],//[0,1,0,1,1,1,0,1]
<< <<X>> || <<X:1>> <= Key>>.//<<0,1,0,1,1,1,0,1>>
动态函数调用
类似java的反射调用,但是要尽量避免这种调用方式,因为这会导致一些分析程序无法发现问题
test()->
apply(bit,add,[5,15]).//20
add(A,B)->
A+B.
算数表达式
+X //正x
-X //负X
X + Y //加法
X - Y //减法
X * Y //乘法
X / Y //浮点除法
bnot X //对X执行按位取反
X div Y //X被Y整除
X rem Y //X被Y整除后余数
X band Y //X和Y按位与
X bor Y //X和Y按位或
X bxor Y //X和Y按位异或
X bsl N //把X向左算数位移N位
X bsr N //把X向右算数位移N位
模块属性
-module(name).
模块声明,必须是文件第一个属性,并且要确保name是文件的文件名
-import(Mod,[Name/Arity,...])
声明要从mod模块中导入参数为Arity个的name方法
-export([Name/Arity,...])
声明希望导出的函数
-compile(Options).
添加一个配置选择到编译器的选择列表中,可以是单个编译器选择也可以是选择列表
ps:-compile(export_all)是导出全部函数,这样就不用显式调用-export来一个个导出了
-vsn(Version).
声明模块版本号,可以是任何值,主要作为分析程序或说明文档作用。
自定义属性及获取
-module(bit).
-vsn(adw).
-ceshi(aa).
-export([test/0]).
test()->
Key = bit:module_info(attributes),
Key.
不传参则全部返回,用beam_lib:chunks("bit.beam",[attributes]).也可以达到同样效果,并且不需要编译器事先载入对应的beam
块表达式
当需要多行表达式但是目标位置只有一行表达式容量时候
test()->
[
begin
Y=X rem 2-1,
Y*2
end
||X<-[1,2,3,4,5] //[0,-2,0,-2,0]
].
函数返回布尔值规范
如果有可能返回两个原子来表达状态,最好用返回true和false来表示。而假如想用布尔值返回,则名字最好写成is_XXX之类的,让人一眼就能看出来这里要返回是或否。使用true和false还有一个好处就是可以充分利用标准函数库,而不需要中转站来分析原子含义。
布尔表达式
not A //逻辑非
A and B //逻辑与
A or B //逻辑或
A xor B //逻辑异或
注释
%是注释符号
动态调用函数
start(Tag) ->
spawn(fun() -> loop(Tag) end).
loop(Tag) ->
sleep(),
Val = b:x(),
io:format("~ts~n",[Val]),
loop(Tag).
sleep() ->
receive
after 3000 -> true
end.
假如你的函数依赖外部函数的话,当你更新的外部函数的team的时候,函数会自动去调用现在存在的那个新的外部函数,不需要额外操作,通过这样可以实现热更新。此外要注意的是erlang最多允许两个版本在允许,即旧版和当前版本。假如出现新版本替换,则原来的旧版程序都会被掐灭,而当前版变旧版,新版变当前版。
转义字符
\b //退格符
\d //删除符
\e //换码符
\f //换页符
\n //换行符
\r //回车符
\s //空格符
\t //制表符
\v //垂直制表符
\x{...} //十六进制符
\^a..\^z //Ctrl+A到Z
\' //单引号
\" //双引号
\\ //反斜杠
\C //C字符的ASCII编码
表达式和表达式序列
表达式必然有一个返回值,所以记录声明和模块属性没返回值不是表达式。表达式序列则指以逗号分割最后以句号结尾的一系列表达式。要注意的是这种表达式只会返回最后一个的值,但是可以使用序列前面绑定的值。
函数引用
有时候我们会希望把函数当参数引用,这时候就要用函数引用
X = fun test/1. //引用本地函数
Y = fun mod:test/1. //引用外部函数
包含文件
-module(he).
-include("./he.hrl").
-export([test/0]).
test()->
#student{name = feng}.
使用hrl文件就可以多个erl文件共享配置,此外还有include_lib,似乎是用来获得包含库的头文件
++与--
A++B 使A和B相加或拼接
A--B 从列表A中移除列表B,假如B中k出现N次则A中只会移除N次