读《Erlang程序设计中文版》,只记录自己容易忘记、还不懂、或者需要注意的内容。
Chapter 2 入门
- 变量可以16进制和32进制记号:16#cafe、32#sugar
- 除号 ”/“ :永远返回浮点数。整除:div 和 求余:rem(都只能用于整数)
- 原子(item)一般以小写字母开头:monday。但用了单引号,就可以任意定义:‘Monday’
- “=”用于模式匹配,对于未绑定变量,才是赋值。“=”右边,不能有未绑定变量
- 字符串就是列表:"abc" = [97,98,99] ,shell下会默认把都是可打印字符的列表,以字符串形式显示。"$"用于字符前,可以获得对应的ASCII的整数值: $a (97)
- 命令f():让shell释放所有变量
Chapter 3 顺序型编程
- 同名不同目的函数,一般用于辅助函数(传默认值)
- 匿名函数不同子句,不要重复fun
Fun = fun({case1,X})->ok; ({case2,X})->error end.
- lists标准库常用函数:
- lists:map(F,L):返回映射后的列表
- lists:filter(P,L):返回列表,元素满足函数P返回值为true
- lists:member(X,L):返回true
- lists:sum(L):对列表各元素求和
- lists:seq(1,N):返回1到N的整数列表
- lists:reverse(L)
- lists:foreach(fun,L) 返回ok,类似map
4. 记录(record)匹配,不需要列出所有项
-record(todo,{status=undefine,who,text}). ... X = #todo{}. %%新建,可以不全指定 X1 = X#todo{status=ok,who="Nick"}. %%更新部分字段 #todo{status=Sta}=X1. %%提取部分字段,不用列出所有项。可用于函数的参数提取
5. rf(记录名):释放记录定义,让记录变成元组
Chapter 4 异常
1. 异常的发生原因:内部错误(模式匹配失败,BIF调用失败:atom_to_list(32)),显式/主动抛错(throw(Exception),exit(Exce),erlang:error(Exce))
2. try-catch 格式
Chapter 5 顺序型编程进阶
1. BIF操纵二进制数据
Ei格式:
4. beam_lib:chunks可以来提取属性。
5. begin..end 块语句,可以合并成相当于一个单个语句
6. 函数值是两个原子值中的一个,用true/false做为返回值,就可以通用、结合其他标准库函数
7. fun Mod:RemoeFun/Arity 和 fun LocalFun/Arity 动态引用函数: lists:map(fun square/1,L). %%square/1 为内部函数
8. --操作符,依次删,没有就不删:[1,2,3,3]--[3]只删第一个3
9. 宏定义,取消宏定义:-undef(MACRONAME) .
11. 引用erlang:make_ref():还不知道怎么用
12. 短路布尔表达式:andelse、orelse
*13. 比特高级语法示例,还没看
Chapter 6 编译并运行程序
1. .erlang在home目录下,里面可以设置加载目录:code:add_patha(FilePath)。shell下,用init:get_argument(home).可以获取home目录位置
2. 用命令行编译运行:
4. shell下输入,webtool:start(),去看错误日志
5. shell中的编辑命令,^t:颠倒两个字母,tab键:提示
6. 写sh脚本自动运行hello.erl,运行前,先给权限:chmod u+x hello.sh,再./hello.sh
Chapter 8 并发编程
1. Pid ! Message 返回值是Message,所以可以Pid1 ! Pid2 ! Msg
2. 服务器和客户端,在erlang中,都看成是进程,只是扮演角色不同
3. Pid = spawn(fun Mod:fun/Arty) 或者 Pid = spawn(fun()->Mod:fun(Args) end)
4. statistics(runtime):运行代码Cpu占用、花费的时间,statistics(wall_clock):真实消耗时间(cpu上消耗+等待的时间),单位微秒
6. send、receive的实质:把消息发到一个进程中的邮箱中,从本进程的邮箱中删除消息。
receive消息,一条条匹配,匹配不到,保存到一个队列中,一旦匹配到,释放队列到邮箱。一条都没匹配到,新消息来就先匹配新消息。
7. register(atomName,Pid),registered()->[],unregister(atomName),whereis(atomName)->Pid | undefined
8. 定时操作
Chapter 9 并发编程中的错误处理
1. link(Pid):进程相互之间建立链接,就会彼此监视。可以通过process_flag(trap_exit,true),设置当前进程为捕获进程,这样就不会自动退出了。
2. 进程消亡:结束,exit(Reason),出错,都会发送{'Exit',Pid,Reason}给链接进程。
3. Pid1向其他进程发送exit:exit(Pid2,Reason),Pid2会收到{'Exit',Pid1,Reason}(trap的话),Pid1装死
4. exit(kill)无法捕获
5. spawn_link(Fun)->Pid,spawn和link同时完成
*6. 9.4.2捕获退出信号(进阶篇)还没看
Chapter 10 分布式编程
1. rpc:call(Node,Mod,Fun,[Arg1,Arg2]),调用远程节点上的函数
2. net_adm:ping(Node) -> pong | pang disconnect_node(Node)->bool() | ignored
3. 分布式的核心就是节点,1个节点就是1个独立进程集的虚拟机
4. jj
Chapter 14 套接字编程
1. 客户端 gen_tcp:connect(Host,Port,[binary,{packet,0}]).->{ok,Socket} | {error,Reason}
gen_tcp:send(Socket,"msg...").->ok | {error,Reason}
receive时,{tcp,Socket,Bin} 或者 {tcp_closed,Socket}
2. 服务端 gen_tcp:listen(Port,[binary,{packet,4},{reuseaddr,true},{active,true}])->{ok,ListenSocket} | {error,Reason}
gen_tcp:accept(ListenSocket) -> {ok,Socket} | {error,Reason}
gen_tcp:close(Socket) -> ok
receive时,同客户端
3. 套接字的三种打开类型:
{active,true}:直接receive end接受,客户端发的太快会淹没消息缓冲区,服务端崩溃
{active,false}:需要gen_recv(Socket,N) -> {ok,Data} | {error,Reason}接受指定字节,但会阻塞客户端,且只对一个套接字有效(待验证)
{active,once}:需要手动inet:setopts(Socket,[{active,once}])
4. 套接字来源: inet:peername(Socket) -> {ok,{Ip_Address,Port}} | {error,Reason}
5. 套接字出错,gen_accept(Listen)的进程崩溃
Chapter 15 ETS和DETS
1. 表的类型:set(后者冲前者)、ordered set、bag(不允许完全相同)、duplicate bag
2. ets:new(TableName,[public,named_table,{read_concurrency,true} |,{wirte_concurrency,true}]),ets:info(Tab,size) -> integer().
3. ets:match(Tab,Pattern) -> [Match].和 ets:select(Tab,MatchSpec) -> [Match].
Chapter 4 异常
1. 异常的发生原因:内部错误(模式匹配失败,BIF调用失败:atom_to_list(32)),显式/主动抛错(throw(Exception),exit(Exce),erlang:error(Exce))
2. try-catch 格式
3. catch中,_:_->捕获所有异常,_->只捕获throw的。用_:Error->error_logger:error_msg("{~p,~p~n}",[Error,erlang:get_stacktrace()])输出栈跟踪信息,获取报错行数try Sequences of try Sequences %%省略格式 Result1->... catch Result2->... Catch1->... catch end Catch1->... %%默认throw型 exit:Catch2->... error:Catch3->... after ... end
Chapter 5 顺序型编程进阶
1. BIF操纵二进制数据
2. 比特语法表达式:<<E1,E2>>
- @spec list_to_binary(L)->Bin L的元素必须是0~255的整数,二进制数或另一个L。不能list_to_binary([a,b,c]).
- @spec split_binary(Bin,Pos)->{Bin1,Bin2}
- @spec term_to_binary(Term)->BIn
- @spec Binary_to_term(Bin)->Term
- size(Bin)
Ei格式:
3. apply(Mod,Fun.[Arg1,..ArgN]):可以动态调用函数
- Value %%默认Type=integer,Unit=1,End=big,Sign=unsigned
- Value:Size
- Value/TypeSpecifierList
- Value:Size/TypeSpecifierList
4. beam_lib:chunks可以来提取属性。
5. begin..end 块语句,可以合并成相当于一个单个语句
6. 函数值是两个原子值中的一个,用true/false做为返回值,就可以通用、结合其他标准库函数
7. fun Mod:RemoeFun/Arity 和 fun LocalFun/Arity 动态引用函数: lists:map(fun square/1,L). %%square/1 为内部函数
8. --操作符,依次删,没有就不删:[1,2,3,3]--[3]只删第一个3
9. 宏定义,取消宏定义:-undef(MACRONAME) .
10. 模式中使用匹配操作符:fun( [ {tag1,{one,A} = Z1,B} = Z2 | T] )->函数中可以直接使用Z1,Z2了,避免两次创建-ifdef(MACRONAME). -define(Fun(X),X*2). -else -define(Fun(X),X*3). -endif.
11. 引用erlang:make_ref():还不知道怎么用
12. 短路布尔表达式:andelse、orelse
*13. 比特高级语法示例,还没看
Chapter 6 编译并运行程序
1. .erlang在home目录下,里面可以设置加载目录:code:add_patha(FilePath)。shell下,用init:get_argument(home).可以获取home目录位置
2. 用命令行编译运行:
3. escript脚本运行 可以不要编译就运行,不懂现在,还有eval不知道怎么运行多个函数erlc -o ebin src/*.erl %%编译到ebin下 erlc hello.erl %%直接编译到当前目录 erl -noshell -pa ebin -s hello start 25 24 -s init stop %%带参数运行hello:start([25,24]) erl -noshell -pa ebin -s hello %%没有函数名,默认启动hello:start() hello.erl start()-> ok. main([A,B])-> io:format("~p~n",[A]), init:stop().
4. shell下输入,webtool:start(),去看错误日志
5. shell中的编辑命令,^t:颠倒两个字母,tab键:提示
6. 写sh脚本自动运行hello.erl,运行前,先给权限:chmod u+x hello.sh,再./hello.sh
*7. makefile还没看#!/bin/sh erl -noshell -pa ebin -s start\ -s init stop
Chapter 8 并发编程
1. Pid ! Message 返回值是Message,所以可以Pid1 ! Pid2 ! Msg
2. 服务器和客户端,在erlang中,都看成是进程,只是扮演角色不同
3. Pid = spawn(fun Mod:fun/Arty) 或者 Pid = spawn(fun()->Mod:fun(Args) end)
4. statistics(runtime):运行代码Cpu占用、花费的时间,statistics(wall_clock):真实消耗时间(cpu上消耗+等待的时间),单位微秒
5. receive语句中after子句执行前,先要匹配一下邮箱。引申出优先匹配和清空邮箱的功能。infinity:无限等待,这样就可以由外部指定是否设置超时了。statistics(runtime), statistics(wall_clock), ... {_,Time1} = statistics(runtime), {_,Time2} = statistics(wall_clock)
6. send、receive的实质:把消息发到一个进程中的邮箱中,从本进程的邮箱中删除消息。
receive消息,一条条匹配,匹配不到,保存到一个队列中,一旦匹配到,释放队列到邮箱。一条都没匹配到,新消息来就先匹配新消息。
7. register(atomName,Pid),registered()->[],unregister(atomName),whereis(atomName)->Pid | undefined
8. 定时操作
tick(Time,Fun)-> receive stop-> void after Time-> Fun(), tick(Time,Fun) end.
Chapter 9 并发编程中的错误处理
1. link(Pid):进程相互之间建立链接,就会彼此监视。可以通过process_flag(trap_exit,true),设置当前进程为捕获进程,这样就不会自动退出了。
2. 进程消亡:结束,exit(Reason),出错,都会发送{'Exit',Pid,Reason}给链接进程。
3. Pid1向其他进程发送exit:exit(Pid2,Reason),Pid2会收到{'Exit',Pid1,Reason}(trap的话),Pid1装死
4. exit(kill)无法捕获
5. spawn_link(Fun)->Pid,spawn和link同时完成
*6. 9.4.2捕获退出信号(进阶篇)还没看
Chapter 10 分布式编程
1. rpc:call(Node,Mod,Fun,[Arg1,Arg2]),调用远程节点上的函数
2. net_adm:ping(Node) -> pong | pang disconnect_node(Node)->bool() | ignored
3. 分布式的核心就是节点,1个节点就是1个独立进程集的虚拟机
4. jj
Chapter 14 套接字编程
1. 客户端 gen_tcp:connect(Host,Port,[binary,{packet,0}]).->{ok,Socket} | {error,Reason}
gen_tcp:send(Socket,"msg...").->ok | {error,Reason}
receive时,{tcp,Socket,Bin} 或者 {tcp_closed,Socket}
2. 服务端 gen_tcp:listen(Port,[binary,{packet,4},{reuseaddr,true},{active,true}])->{ok,ListenSocket} | {error,Reason}
gen_tcp:accept(ListenSocket) -> {ok,Socket} | {error,Reason}
gen_tcp:close(Socket) -> ok
receive时,同客户端
3. 套接字的三种打开类型:
{active,true}:直接receive end接受,客户端发的太快会淹没消息缓冲区,服务端崩溃
{active,false}:需要gen_recv(Socket,N) -> {ok,Data} | {error,Reason}接受指定字节,但会阻塞客户端,且只对一个套接字有效(待验证)
{active,once}:需要手动inet:setopts(Socket,[{active,once}])
4. 套接字来源: inet:peername(Socket) -> {ok,{Ip_Address,Port}} | {error,Reason}
5. 套接字出错,gen_accept(Listen)的进程崩溃
Chapter 15 ETS和DETS
1. 表的类型:set(后者冲前者)、ordered set、bag(不允许完全相同)、duplicate bag
2. ets:new(TableName,[public,named_table,{read_concurrency,true} |,{wirte_concurrency,true}]),ets:info(Tab,size) -> integer().
3. ets:match(Tab,Pattern) -> [Match].和 ets:select(Tab,MatchSpec) -> [Match].
4. aaets:new(t ,[named_table]). ets:insert(t,[{1,2},{2,b},{3,c},{4,d}]. MS = ets:fun2ms( fun({X,Y}) -> when (X>1) or (X<5) -> {Y} end). > [{{'$1','$2'},[{'or',{'>','$1',1},{'<','$1',5}}],[{{'$2'}}]}] ets:select(t,MS). > [{2},{b},{c},{d}].