@delight
2016-02-09T11:39:03.000000Z
字数 2528
阅读 1649
erlang
fp
对于学习过Haskell的人来说,学习Erlang并没有太大的难度。
=
作模式匹配,用|
做头尾区分,用双引号表示字符串(本质是一串数字,可以用$
取得字符对应的数字);.
表示模式终结,,
用来分割参数,函数;;
用来分割子句;func
关键字用来定义匿名函数;
func(X, Y) -> math:sqrt(X*X + Y*Y) end.
可以把返回值放到括号里面。
6. 标准库lists
里面含有很多常见的函数,如map
, reduce
, filter
等;
7. 没有for
循环,和haskell一样,使用尾递归;
8. 使用import
, export
, module
来导入/导出/声明模块;
9. 列表解析,格式是[X *2 || X <- L].
qsort([]) -> [];
qsort([H|T]) ->
qsort([X || X <- T, X < H]) ++
[H] ++
qsort([X || X <- T, X >= H]).
when
。使用,
表示andalso
语义, 使用orelse
而不是or
因为后者不是短路求值;record
表示字典,声明方式:
-record(todo, {stats=reminder, who=joe, text})
需要将其存放在.hrl
后缀的文件中,然后使用rr
读取。
X=#todo{}.
Y=#todo{status=urgent, text="Fix errata in book"}.
Z=Y#todo{status=done}.
#todo{who=W, text=Txt} = Z %模式匹配
可以使用is_record
做模式匹配;
12. case xxx of Pattern1 [when Guard1] -> xxx end
odds_and_evens_acc(L) ->
odds_and_evens_acc(L, [], []).
odds_and_evens_acc([H|T], Odds, Evens) ->
case (H rem 2) of
1 -> odds_and_evens_acc(T, [H|Odds], Evens);
0 -> odds_and_evens_acc(T, Odds, [H|Evens])
end;
odds_and_evens_acc([], Odds, Evens) ->
{Odds, Evens}.
try...catch..after...end
格式,非常类似java;2#01011
其中#
前面是进制,浮点数可以用科学计数法,即-2.3e+6
等;put
,get
, get_keys
, erase
等函数进行操作;但是如果使用进程字典,代码就不再是没有副作用的,因此要避免使用;erlang:make_ref()
来创建引用;==
, /=
, =:=
全等,=/=
不全等;数值比较会有隐式转换;==
仅限于浮点数和整数的比较,大部分情况下,应该使用=:=
;number
<atom
<reference
<fun
<port
<pid
<tuple
<list
<binary
;下划线变量:仅用来声明不准备使用的变量(占位符);或者用来调试;
对于大的程序,还是要使用makefile的,然而直到今天我还是不会写makefile,不过我决定抽个时间学习以下cmake的使用;使用code:get_path()
查看搜索路径,code:add_patha
, code:add_pathz
用来增加新目录;
~/.erlang
下增加一些命令,当启动erl
shell时,会先执行这里的初始化语句;当前目录下的.erlang
会覆盖home下的执行优先级。可以使用init:get_argument(home)
确定home的路径(for windows);escript
命令执行而无需编译(解释器)。escript的语法与erlang本身略有不同。当然我想不到在什么情况下要写erlang脚本。。。因为erlang并不是一门好的脚本语言。python才是现在的最优选择:)Pid=spawn(Fun)
;Pid ! Message
,异步发送。返回值是消息本身,这意味着使用Pid1 ! Pid2 ! M
会将M发送到所有的Pid中;receive ... end
, 接收一个发送到当前进程的消息;格式是:
receive
Pattern1 [When Guard1] ->
Expression1;
Pattern2 [When Guard2] ->
Expression2;
after Time -> %超时
Expressions
end
after
设置,计时器到达后也会触发上述规则;
register(Name, Pid) %将Pid注册为Name
unregister(Name)
whereis(Name) -> Pid | undefined %检测是否注册成功
registered() %已注册进程list
link(Pid)
在两个进程之间建立联系。二者之中任意一个挂掉,另一个都会收到系统通知;Erlang并不难,但是OTP很难。Erlang设计很用心,目标很明确,对于分布式大型系统的构建提供了很多基础支撑。缺点是生态系统略显封闭,社区不活跃,各种第三方库支持不全。相比之下,个人更看好Go的发展,虽然后者并不是为构建大规模系统而生,但是CPS模型的并发写起来也很舒服,加上简单的语法,快速的编译过程,完善的生态链,杰出的性能,是一个很不错的工具。
目前来看,Skynet+Lua就是仿制了Erlang的思想。