今天花了2各种头,看了一下programming erlang的前三章,由于自己对scheme和haskell都有一些了解,因此觉得语法方面,erlang和他们挺相似的.
顺便发下牢骚,emacs实在是用不习惯,可是vi的erlang插件实在是烂,郁闷..
这边只是一个简要的描述.
1整数
erlang里面的整数和scheme里面的是一样的都是允许任意长度的(只要不超出机器字长的限制):
如果你想指定一个数字的进制,你可以这样做:
2变量
在erlang里面变量的命名必须第一个字母是大写的,而且由于erlang是纯粹的FP,因此他的变量是不可变的(scheme就不是纯粹的FP):
这边可以看到重复赋值会报错.
在这里要注意,在erlang中"="号并不是一般语言中的赋值的意思,而是模式匹配(pattern matching)的操作.当一个变量被赋值之后,erlang会将这个变量绑定到这个值上.
我们再看下面的例子:
这边我猜测,X,Y其实共享1234.
3 浮点数
这边注意一下div和 /的区别就行了.
4 atom
erlang中,atom的定义以小写字母开头,他经常被用来表示非字符的常量,他还可以用单引号括起来,这样就能使用大写字母开头的atom了.
5 tuple
tuple主要是将一些元素分组,它和c中的结构体有些类似,不过他里面的域是没有名字的。因此为了更容易让人理解你的代码,建议在tuple的第一个元素使用atom来描述你的tuple:
这边要注意"_"符号,他其实也就是一个占位符了:
6 list
其实list也就是scheme中的列表了,换了个名字而已...
list是用中括号,将一些元素括起来,中间用逗号隔开:
假设我们有个list L,那么通过表达式[H|T]=L,H,T都没有被绑定,H将会是L的第一个元素,T则将是除去第一个元素外的list:
7 string
在erlang中,其实字符串也就是一个整数list了,虽然他看起来也是用双引号括起来的:
我们可以这样创建一个字符串:
如果有一个数字不能打印,那么就是直接打印出整个数字list:
在上面的代码里,1不是一个可打印的字符.
8 moudle
模块是erlang的基本单元,所有的函数都写在模块里,而模块都被存储在.erl文件里面,模块必须被编译成.beam文件后才能被运行.
这边函数的定义的话,其实也就类似oo里面的多态了.不过这边是函数的多态罢了.这边要注意要用;来隔开,如果你用"."的话,就要重载了.
-module代表模块的名字,-export表示这个模块中的那个方法能被外面的模块所使用,area/1说明外部模块可以使用的是area的只有一个参数的方法。-import则是导入外部模块的方法.
这就是一个简单的模块.可以这样的使用他:
9 fun 函数
其实也就是lambda了,换个名字而已:
通过fun我们可以轻松的对函数curry化:
10 高阶函数
比如map,filter之类的高阶函数,erlang也都是有的:
11 List Comprehensions
也就是python里面的差不多了,不过语法差些而已:
看个快速排序:
12 guard
guard是一种我们能够增强我们的模式匹配的一种结构,假设我们想写一个max(X,Y).我们可以用guard来这样写:
Guard Sequence是一个或多个Guard,他们都用;来隔开,就是或的意思了,也就是说,有一个为真,整个就为真.我们还可以用oralso来替代.
而guard则是一个或者多个表达式,他们用,隔开,就是与的意思,也就是说,如果有一个为假,则整个就为假.去我们还可以用andalso来替代.
13 record
定义一个record:
我们能够在erl里面使用rr来读取这个record:
创建和修改record:
这边要注意,当使用X1#todo...时,他会先复制一个record然后再进行更新操作,因此此时X1,并不会改变.
得到一个record中的域的值:
一个record其实也就是一个有名字的tuple:
14 其他的表达式
case :
if :
最后看一段将一个list分为计数和偶数两个组的更高效的写法(相比较使用List Comprehensions:
使用List Comprehensions:
更高效的写法:
顺便发下牢骚,emacs实在是用不习惯,可是vi的erlang插件实在是烂,郁闷..
这边只是一个简要的描述.
1整数
erlang里面的整数和scheme里面的是一样的都是允许任意长度的(只要不超出机器字长的限制):
3> 123456789 * 987654321 * 112233445566778899 * 998877665544332211.如果你想指定一个数字的进制,你可以这样做:
4> 16#cafe * 32#sugar.
15776825114342变量
在erlang里面变量的命名必须第一个字母是大写的,而且由于erlang是纯粹的FP,因此他的变量是不可变的(scheme就不是纯粹的FP):
2> X=123456789.
123456789
4> X = 1234.
=ERROR REPORT==== 11-Sep-2006::20:32:49 ===
Error in process <0.31.0> with exit value:
{{badmatch,1234},[{erl_eval,expr,3}]}
** exited: {{badmatch,1234},[{erl_eval,expr,3}]} **这边可以看到重复赋值会报错.
在这里要注意,在erlang中"="号并不是一般语言中的赋值的意思,而是模式匹配(pattern matching)的操作.当一个变量被赋值之后,erlang会将这个变量绑定到这个值上.
我们再看下面的例子:
2> X=1234.
1234
4> X =1234.
1234
5> Y=1234.
1234
6>X=Y.
1234
7> X=123456.
出错...这边我猜测,X,Y其实共享1234.
3 浮点数
1> 5/3.
1.66667
2> 4/2.
2.00000
3> 5 div 3.
1
4> 5 rem 3.
2
5> 4 div 2.
2
6> Pi = 3.14159.
3.14159
7> R = 5.
5
8> Pi * R * R.
78.5397
这边注意一下div和 /的区别就行了.
4 atom
erlang中,atom的定义以小写字母开头,他经常被用来表示非字符的常量,他还可以用单引号括起来,这样就能使用大写字母开头的atom了.
1> hello.
hello5 tuple
tuple主要是将一些元素分组,它和c中的结构体有些类似,不过他里面的域是没有名字的。因此为了更容易让人理解你的代码,建议在tuple的第一个元素使用atom来描述你的tuple:
1> Person = {person,
{name, joe},
{height, 1.82},
{footsize, 42},
{eyecolour, brown}}.这边要注意"_"符号,他其实也就是一个占位符了:
1>Person={person,{name,{first,joe},{last,armstrong}},{footsize,42}}.
{person,{name,{first,joe},{last,armstrong}},{footsize,42}}
2> {_,{_,{_,Who},_},_} = Person.
{person,{name,{first,joe},{last,armstrong}},{footsize,42}}6 list
其实list也就是scheme中的列表了,换了个名字而已...
list是用中括号,将一些元素括起来,中间用逗号隔开:
1> ThingsToBuy = [{apples,10},{pears,6},{milk,3}].
[{apples,10},{pears,6},{milk,3}]假设我们有个list L,那么通过表达式[H|T]=L,H,T都没有被绑定,H将会是L的第一个元素,T则将是除去第一个元素外的list:
4> [Buy1|ThingsToBuy2] = ThingsToBuy1.
[{oranges,4},{newspaper,1},{apples,10},{pears,6},{milk,3}]7 string
在erlang中,其实字符串也就是一个整数list了,虽然他看起来也是用双引号括起来的:
3> [83,117,114,112,114,105,115,101].
"Surprise"我们可以这样创建一个字符串:
6> [I-32,$u,$r,$p,$r,$i,$s,$e].
"Surprise"如果有一个数字不能打印,那么就是直接打印出整个数字list:
4> [1,83,117,114,112,114,105,115,101].
[1,83,117,114,112,114,105,115,101].在上面的代码里,1不是一个可打印的字符.
8 moudle
模块是erlang的基本单元,所有的函数都写在模块里,而模块都被存储在.erl文件里面,模块必须被编译成.beam文件后才能被运行.
-module(geometry).
-export([area/1]).
area({rectangle, Width, Ht}) -> Width * Ht;
area({circle, R}) -> 3.14159 * R * R.这边函数的定义的话,其实也就类似oo里面的多态了.不过这边是函数的多态罢了.这边要注意要用;来隔开,如果你用"."的话,就要重载了.
-module代表模块的名字,-export表示这个模块中的那个方法能被外面的模块所使用,area/1说明外部模块可以使用的是area的只有一个参数的方法。-import则是导入外部模块的方法.
这就是一个简单的模块.可以这样的使用他:
1> c(geometry).
{ok,geometry}
2> geometry:area({rectangle, 10, 5}).
50
3> geometry:area({circle, 1.4}).
6.157529 fun 函数
其实也就是lambda了,换个名字而已:
5> Hypot = fun(X, Y) -> math:sqrt(X*X + Y*Y) end.
#Fun<erl_eval.12.115169474>
6> Hypot(3,4).
5.00000通过fun我们可以轻松的对函数curry化:
1> Fruit = [apple,pear,orange].
[apple,pear,orange]
2> MakeTest = fun(L) -> (fun(X) -> lists:member(X, L) end) end.
#Fun<erl_eval.6.56006484>
3> IsFruit = MakeTest(Fruit).
#Fun<erl_eval.6.56006484>
4> IsFruit(pear).
true
5> IsFruit(apple).
true10 高阶函数
比如map,filter之类的高阶函数,erlang也都是有的:
12> L = [1,2,3,4].
[1,2,3,4]
17> lists:map(Even, [1,2,3,4,5,6,8]).
[false,true,false,true,false,true,true]
18> lists:filter(Even, [1,2,3,4,5,6,8]).
[2,4,6,8]11 List Comprehensions
也就是python里面的差不多了,不过语法差些而已:
1> L = [1,2,3,4,5].
[1,2,3,4,5]
4> [2*X || X <- L ].
[2,4,6,8,10]看个快速排序:
qsort([]) -> [];
qsort([Pivot|T]) ->
qsort([X || X <- T, X < Pivot])
++ [Pivot] ++
qsort([X || X <- T, X >= Pivot]).
1> L=[23,6,2,9,27,400,78,45,61,82,14].
[23,6,2,9,27,400,78,45,61,82,14]12 guard
guard是一种我们能够增强我们的模式匹配的一种结构,假设我们想写一个max(X,Y).我们可以用guard来这样写:
max(X, Y) when X > Y -> X;
max(X, Y) -> Y.Guard Sequence是一个或多个Guard,他们都用;来隔开,就是或的意思了,也就是说,有一个为真,整个就为真.我们还可以用oralso来替代.
is_atom(L) orelse (is_list(L) andalso length(L) > 2)而guard则是一个或者多个表达式,他们用,隔开,就是与的意思,也就是说,如果有一个为假,则整个就为假.去我们还可以用andalso来替代.
A >= -1.0 andalso A+1 > B13 record
定义一个record:
-record(todo, {status=reminder,who=joe,text}).我们能够在erl里面使用rr来读取这个record:
1> rr("records.hrl").
[todo]创建和修改record:
2> X=#todo{}.
#todo{status = reminder,who = joe,text = undefined}
3> X1 = #todo{status=urgent, text="Fix errata in book"}.
#todo{status = urgent,who = joe,text = "Fix errata in book"}
4> X2 = X1#todo{status=done}.
#todo{status = done,who = joe,text = "Fix errata in book"}这边要注意,当使用X1#todo...时,他会先复制一个record然后再进行更新操作,因此此时X1,并不会改变.
得到一个record中的域的值:
8> X2#todo.text.
"Fix errata in book"一个record其实也就是一个有名字的tuple:
11> X2.
#todo{status = done,who = joe,text = "Fix errata in book" }
12> rf(todo).
ok
13> X2.
{todo,done,joe,"Fix errata in book" }14 其他的表达式
case :
filter(P, [H|T]) ->
case P(H) of
true -> [H|filter(P, T)];
false -> filter(P, T)
end;
filter(P, []) ->
[].if :
if
Guard1 ->
Expr_seq1;
Guard2 ->
Expr_seq2;
...
end最后看一段将一个list分为计数和偶数两个组的更高效的写法(相比较使用List Comprehensions:
使用List Comprehensions:
odds_and_evens(L) ->
Odds = [X || X <- L, (X rem 2) =:= 1],
Evens = [X || X <- L, (X rem 2) =:= 0],
{Odds, Evens}.
5> lib_misc:odds_and_evens([1,2,3,4,5,6]).
{[1,3,5],[2,4,6]}更高效的写法:
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}.
本文介绍了Erlang的基础知识,包括整数、浮点数、原子类型、元组、列表等基本数据类型,并讲解了函数定义、模块使用、记录定义等高级特性。
5233

被折叠的 条评论
为什么被折叠?



