鸿 网 互 联 www.68idc.cn

当前位置 : 服务器租用 > 编程语言开发 > erlang > >

【原译】Erlang列表处理(Efficiency Guide)

来源:互联网 作者:佚名 时间:2012-11-15 13:26
摘要: 翻译太菜希望大牛指正。以后会逐渐加入自己写的注释和疑问,有些地方自己也不太了解,知道或者感兴趣的同学可以指出来,一起讨论一下。 ===================================================================================================== List

 

摘要: 翻译太菜希望大牛指正。以后会逐渐加入自己写的注释和疑问,有些地方自己也不太了解,知道或者感兴趣的同学可以指出来,一起讨论一下。

=====================================================================================================

List handling 1  Creating a list 创建一个列表

Lists can only be built starting from the end and attaching list elements at the beginning. If you use the ++ operator like this

列表只能从尾端开始创建,从头部加入元素。如果你像这样使用++操作符

 

List1 ++ List2

 

you will create a new list which is copy of the elements in List1, followed by List2. Looking at how lists:append/1 or ++would be implemented in plain Erlang, it can be seen clearly that the first list is copied:

你将创建一个新的列表,这个列表是List1的副本加上List2。看看lists:append/1函数或者++操作符在Erlang里面是怎样实现的,可以明了地看到第一个列表被复制了:(%% 取一个输入列表的元素,加到新的列表中 %%)

 

append([H|T], Tail) -> [H|append(T, Tail)]; append([], Tail) -> Tail.

 

So the important thing when recursing and building a list is to make sure that you attach the new elements to the beginning of the list, so that you build a list, and not hundreds or thousands of copies of the growing result list.

所以在递归遍历和构造一个列表的时候,香港空间,要确保把新的元素附加到列表的头部,这样就能避免产生成百上千的列表的副本。

Let us first look at how it should not be done:

让我们首先来看看不应该使用的方法:

DO NOT

 

bad_fib(N) -> bad_fib(N, 0, 1, []). bad_fib(0, _Current, _Next, Fibs) -> Fibs; bad_fib(N, Current, Next, Fibs) -> bad_fib(N - 1, Next, Current + Next, Fibs ++ [Current]).

 

Here we are not a building a list; in each iteration step we create a new list that is one element longer than the new previous list.

这里我们并不是在创建一个列表;每一次迭代中,我们都产生了一个新的列表,这个新的列表比上次产生的列表还多一个元素。

To avoid copying the result in each iteration, we must build the list in reverse order and reverse the list when we are done:

为了避免在每次迭代中复制最后的结果,我们必须以相反顺序来构造列表,然后在结束的时候反转列表:

DO

 

tail_recursive_fib(N) -> tail_recursive_fib(N, 0, 1, []). tail_recursive_fib(0, _Current, _Next, Fibs) -> lists:reverse(Fibs); tail_recursive_fib(N, Current, Next, Fibs) -> tail_recursive_fib(N - 1, Next, Current + Next, [Current|Fibs]).


 

2  List comprehensions 列表解析

Lists comprehensions still have a reputation for being slow. They used to be implemented using funs, which used to be slow.

列表解析仍然被认为是效率慢的。它们以前是使用函数来实现的,而函数过去也是效率慢的。

In recent Erlang/OTP releases (including R12B), a list comprehension

在最近的Erlang/OTP版本中(包括R12B),列表解析

 

[Expr(E) || E <- List]

 

is basically translated to a local function

被转换成一个本地函数

 

'lc^0'([E|Tail], Expr) -> [Expr(E)|'lc^0'(Tail, Expr)]; 'lc^0'([], _Expr) -> [].

 

In R12B, if the result of the list comprehension will obviously not be used, a list will not be constructed. For instance, in this code

在R12B版本中,如果列表解析的结果明确表示出将不会被使用的,那么列表将不会被构造出来。例如,在下面这段代码中

 

[io:put_chars(E) || E <- List], ok.

 

or in this code

或者下面这段代码

 

. . . case Var of ... -> [io:put_chars(E) || E <- List]; ... -> end, some_function(...), . . .

 

the value is neither assigned to a variable, nor passed to another function, nor returned, so there is no need to construct a list and the compiler will simplify the code for the list comprehension to

列表里面的元素既不会赋值给一个变量,也不会传给另外一个函数,或者直接返回,所以这种情况下是没有必要构造一个列表的,编译器会简单地把列表解析的代码简化成下面的形式(%% 一是没有了列表结构,二是用了尾递归 %%)

 

'lc^0'([E|Tail], Expr) -> Expr(E), 'lc^0'(Tail, Expr); 'lc^0'([], _Expr) -> [].


 

3  Deep and flat lists 深度扁平列表
网友评论
<