Chinaunix首页 | 论坛 | 博客
  • 博客访问: 5519862
  • 博文数量: 763
  • 博客积分: 12108
  • 博客等级: 上将
  • 技术积分: 15717
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-28 21:21
个人简介

业精于勤,荒于嬉

文章分类

全部博文(763)

文章存档

2018年(6)

2017年(15)

2016年(2)

2015年(31)

2014年(14)

2013年(87)

2012年(75)

2011年(94)

2010年(190)

2009年(38)

2008年(183)

2007年(28)

分类: LINUX

2013-07-15 11:41:52

一月 22, 2011


1.1. 基础知识

1.1.1.      进程

erlangprocess并不是OS的进程,而是虚拟的进程;进程之间的切换是在用户态进行,开销会比OS的进程小得多。

以后只要提到进程,没有特殊说明,都是指erlang的进程;

最多能有多少进程?没有明确限制,与内存有关,物理内存用完时,会使用虚拟内存;

1.1.2.      OTP

OTP: Open Telecom Platform

不要被名字所混淆,它实际上是用于一套搭建分布式高容错**器的程序库;

 

1.1.3.      变量赋值特性

变量只能被赋值一次,即不能写这样代码:X = X+1

 

2.   语法

 

2.1. 数据类型

2.1.1.    Variables

可赋值的变量,但仅可赋值一次,不能再修改;

只能用大写字母开头,并且用大写字母开头的字符串一律会被视为Variable

也就是说:函数也不能用大写开头

“Absence of Side Effects MeansWe Can Parallelize Our Programs”

例子:

       X = 123456789.  

       其中X就是变量

2.1.2.    Atom

Atom用来表示非数字的常量;

以小写字面开头,后面可以是字母、下划线或者@字符

如果要用大写字母开头的atom,可以使用单引号括起来;

例子:

       X = ok  

       其中ok就是atomX为变量;

2.1.3.    Tuple

“a fixed number of items into a single entity

{}包括起来的数据类型;类似C语言的struct

{apples,10} 第一项是atom类型,第二项是数字

         Tuple可以嵌套,它的元素也可以是tuple

Tuple里面的数据不像C++Java有变量名,因此,习惯于将他们的第一个数据用atom变量来做描述;

         例子:

Person = {person,

{name, joe},

{height, 1.82},

{footsize, 42},

{eyecolour, brown}}.

              这个tuple里就用第一项来表示名字;

2.1.4.    List

[]包括起来的数据类型,如[{apples,10},{pears,6},{milk,3}]

         List的展开:[X|Y] = L.

              X将被赋值为L的第一个子项,Y为除了第一个子项外的其它子项;

         这种展开的方式将很利于递归遍历;

         例子:

ThingsToBuy1 = [{oranges,4},{newspaper,1}|ThingsToBuy].

[Buy1|ThingsToBuy2] = ThingsToBuy1.

              第一句是进行list的赋值;

              第二句则将list分成两部分,以准备进行进一步操作;

2.1.5.    String

String其实是list

比如[83,117,114,112,114,105,115,101]. 其实是“Surprise”

Erlang字符集是Latin-1ISO-8859-1),

         目前最新的版本里,erlang已经加入了Unicode的支持

2.1.6.    -Record

Tuple对象,当成员很多时,会很难记忆,record就是为了解决这个问题;

Record declarations can be used only in Erlang source code modules and not in the shell.

Record就是tuple,但在源码中可以让tuple使用起来想C语言的struct一样

shell里面使用之前,要先用rr进行预处理,但源码好像不需要

-record(todo, {status=reminder,who=joe,text}).

 

1> rr(”records.hrl”).

[todo]

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”}

5> #todo{who=W, text=Txt} = X2.

#todo{status = done,who = joe,text = “Fix errata in book”}

6> W.

joe

7> Txt.

“Fix errata in book”

 

2.2. 句法

2.2.1.    运算符

X > Y            X大于Y

X < Y            X小于Y

X =< Y          X小于或等于Y

X >= Y          X大于或等于Y

X == Y          X等于Y

X /= Y           X不等于Y

X =:= Y        XY完全相等(包括数据类型)

X =/= Y        XY不完全相等

 

       L ++ L2          list append

 

2.2.2.    分隔符

Erlang中的“.”(Period)表示完整函数、参数、数据结果的定义结束;

Erlang中的“,”(Comma)用来分隔参数、模式匹配等,与C语言类似;

       在语句中间出现时,表示两个语句是顺序执行的关系

Erlang中的“;”(Semicolon)用来表示分支,前后句的关系是或;

    Pattern1 ->

Expressions1;

Pattern2 ->

Expressions2;

              先匹配Pattern1,如果匹配成功,执行表达式Expressions1,如果不成功,匹配Pattern2

       例子:

              check(A) ->

       if

              A > 0A=<100 ->

                     io:format(”>0″);

              A > 100 ->

                     io:format(”>100″)

       end.

2.2.3.    模式匹配

模式匹配是erlang语法里面非常关键的内容,在赋值、函数定义、条件判定各种情况都会出现;

比如:{X, Y} = {1,2},这个赋值就完成了依次模式匹配,如果成功,将会吧X赋值为1Y赋值为2

 

模式匹配的例子:

Pattern

Term

Result

{X,abc}

{123,abc}

Succeeds → 123

{X,Y,Z}

{222,def,”cat”}

Succeeds → 222Y→ def,

→ “cat”

{X,Y}

{333,ghi,”cat”}

Fails—the tuples have

different shapes

X

True

Succeeds → true

{X,Y,X}

{{abc,12},42,{abc,12}}

SucceedsX{abc,12}Y→ 42

{X,Y,X}

{{abc,12},42,true}

Failscannot be both

{abc,12} and true

[H|T]

[1,2,3,4,5]

Succeeds H1T[2,3,4,5]

[H|T]

“cat”

Succeeds H99“at”

[A,B,C|T]

[a,b,c,d,e,f]

Succeeds AaB→ b,

C→ cT→ [d,e,f]

 

2.2.4.    Guard

一种非常灵活的表达式,可以放在各种场景下使用,它的结果要么是true,要么是false;是对模式匹配的有力扩展;

使用场景举例:

       在函数定义时使用:

fun(arg) when Guard -> Expressions.

              例子:

max(X, Y) when X > Y -> X;

max(X, Y) -> Y.

if语句中使用:

       if

Guard -> Expressions;

Guard -> Expressions;

true -> Expressions

end

       例子:

              check(A) ->

       if

              A > 0, A=<100 ->

                     io:format(”>0″);

              A > 100 ->

                     io:format(”>100″)

       end.

case语句中:

       case Expression of

Pattern1 [when Guard1] -> Expr_seq1;

Pattern2 [when Guard2] -> Expr_seq2;

end

       例子:

check2(A, B) ->

    case A of

           0 when B>0 -> io:format(”A:0 B>0″);

           0 -> io:format(”A:0 B=0″);

           else -> io:format(”else”)

    end.

 

组合使用的guard

       Guard Sequences:  either a single guard or a series of guards, separated by semicolons (;)

              Guard1; Guard2; Guard3; Guard4

       Guard: a series of guard expressions, separated by commas (,).

              Guard1, Guard2, Guard3, Guard4

Guard的使用限制:

       In addition, guards cannot be user-defined boolean expressions, since we want to guarantee that they are side effect free and terminate.

       所以,Guard不能是自定义的表达式,只能是:

1The atom true
2
Other constants(terms and bound variables)all evaluate to false
3
Calls to the guard predicates and to the BIFs
4
Term comparisons
5
Arithmetic expressions
6
Boolean expressions
7
Short-circuit boolean expressions

 

2.2.5.    case表达式

case表示式类似于C++里面的switch,不过更为强大;

case Expression of

   Pattern1 [when Guard1] -> Expr_seq1;

   Pattern2 [when Guard2] -> Expr_seq2;

   …

end

首先执行Expression,执行的结果进行Pattern模式匹配,匹配成功,则返回Expr_seq的结果;从第一个开始,逐一进行匹配,直到匹配到为止,如果无一匹配成功,会抛出异常;

       例子:

filter(P, [H|T]) ->

case P(H) of

true -> [H | filter(P, T)];

false -> filter(P, T)

end;

filter(P, []) ->

[].

       表达其它的方式:

              Case Expression of

                     {true, Data} -> io:format(”ok”);

                     Others -> io:format(”~p~n”, xxx)

              end.

 

2.3. 函数

2.3.1.    普通函数定义

同函数名,参数个数相同的函数被视为同一个函数,各个函数定义指尖必须用分号“;”(Semicolon)分隔,存在“或”的关系,根据模式匹配结果决定调用到哪里;

       例子:

              area({rectangle, Width, Ht}) -> Width * Ht;

area({square, X}) -> X * X;

area({circle, R}) -> 3.14159 * R * R.

              这表明,当函数的第一个参数是rectangle时,调用到第一个函数,是square时,调用到第二个函数,依次类推;

 

       同函数名,不同参数个数的函数视为不同的函数;

2.3.2.    funs定义

funs是匿名的函数,可以方便定义小函数,并马上使用,类似pythonlambda函数;

       例子:

              Z = fun(X) -> 2*X end.

              Z(2).

 

2.3.3.    Tail-Recursive

loop() ->

       xxx(),

       loop().

       这种写法最后的loop()调用叫tail-recursive,这种调用是用goto实现的,所以不会消耗调用堆栈的空间;

阅读(1403) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~