Erlang中List和Tuple之间的区别

时间:2014-10-07 03:50:07

标签: functional-programming erlang

Erlang中列表和元组之间的主要区别是什么?模式匹配如何区分每个。

4 个答案:

答案 0 :(得分:9)

@Arunmu提供的link回答了问题的第一部分。您可以使用警卫区分这些数据结构:

do_something(List) when is_list(List) ->
    io:format("I got the list ~p", [List]);
do_something(Tuple) when is_tuple(Tuple) ->
    io:format("I got tuple ~p", [Tuple]).

但实际上,你通常以这样一种方式设计你的函数,你知道,如果它采用元组或列表并使用模式匹配来获取元素。如果您知道它有多少元素,您可以像这样模式匹配列表:

[A, B, C] = [1, 2, 3] # A becomes 1, B becomes 2, C becomes 3

但通常,您可以利用列表递归性质。每个列表都是:

  • 空列表
  • 或者它是头部(第一个元素)和尾部。

这是模式匹配,你经常会使用:

[H | T] = [1, 2, 3] # H becomes 1, T becomes [2, 3]
[H2 | T2] = [1] # H becomes 1, T becomes []
[H3 | T3] = [] # gives error badmatch

因此处理列表的函数通常是递归的:

do_stuff([]) ->
     finished; # there are no more elements
do_stuff([H | T]) ->
     do_something_with(H),
     do_stuff(T).

所以你不必知道列表的长度是多少来处理所有元素。当你使用元组时,你知道它们有多大。典型的模式匹配是:

{A, B} = {lol, rotfl} # A becomes lol, B becomes rotfl
{A, _} = {troll, trololo} # A becomes troll

元组经常用于标记事物。当您收到来自其他流程的消息时,请使用receive

receive
    Request -> do_something_with(Request)
end.

但我们不知道,如果请求有效或者某些其他进程错误地发送了某些内容。我们可以使用atom request标记Request,并确保调用进程始终指定自己的pid:

receive
    {request, Pid, Request} ->
        Response = do_something_with(Request),
        Pid ! Response;
    _ -> ignore_message
end.

答案 1 :(得分:4)

它们是不同的数据类型,具有不同的实现和操作成本:

元组通常用于表示可能不同类型固定数量值的集合 ,您希望能够在恒定时间内访问任何值。它们还用于区分正常返回(例如{ok, Value})与错误返回(例如error)而不使用异常。

列表通常用于表示相同类型的任意数量值的集合 ,您希望能够以迭代方式处理元素(例如,使用mapfold操作)。

元组匹配的模式(例如{A,B,C})通常与特定大小的元组和/或某些元素的特定值匹配。

列表匹配的模式(例如[H|T])通常与第一个和其余元素匹配。

答案 2 :(得分:2)

我会尝试回答何时使用元组或列表。它们都是erlang术语的集合,因为它们不像任何其他erlang变量那样可变,所以差异不是固定大小。

元组:当您在编写程序时知道它将包含多少条款时,您将使用元组,当所有条款具有特殊含义并且您将能够使用它们访问它们时位置。一个很好的例子可以是点P = {X,Y,Z}的坐标。

当您认为应用程序的未来发展可能会在集合中引入新术语时,您可能会选择一条记录:具有一些语法功能的命名元组,以按名称访问每个元素,示例是代表员工的记录(姓名,地址,出生地,代码,技能列表)也许您稍后会添加一个电话号码,一封电子邮件......

经常使用的是返回多个值或标记值({ok,Value},{error,Reason})。

列表:列表可以递归定义:它可以是空列表[],也可以是2个元素的构造,即Head和Tail,其中head可以是任何erlang术语,并且尾部是一个列表(我说的只是正确的列表)。当您无法知道何时编写程序时,您将使用此列表。服务器可以在列表中存储连接的客户端的名称。你通常会递归地查看一个列表,所以元素通常是一致的(名称列表,pid列表......)或者使用类似于proplist的“typed”。

这两个元素是更复杂数据结构的基础砖(如树

答案 3 :(得分:1)

基本上,两者都用于完全不同的目的。


元组

1.syntax:{a ,b, c .. z}.

2.Purpose:当您希望某些数据按特定模式分组时,您将使用元组。

例如,我需要昨天的日落和日出时间,我更有可能在这里使用元组而不是列表,记录,ordict等,因为它完全适合该法案。

{sunrise,7.00},{sunset,18.30}

3.Pattern Matching:Tuple支持模式匹配。这就是它的完成方式

tuplePatternMatching({A,B},{C,D}) ->
 io:format("~p ~p",A @ B),
io:format("~p ~p",C @ D) . #sunrise @ 7 #sunset at 18.30

列表

1.pntax:[a,b,c .. z]。

2.目的:一般情况下,我们在需要一些数据时使用它,共享共同的性质被组合在一起。

例如,我需要过去7天的日落时间,我更有可能在这里使用List而不是元组,记录,ordict等。

Sunset = [18,18.01,18.02,18.03,18.04,18.05,18.06]

3.Pattern Matching,Recursion,Operations:List也支持模式匹配,但我们也将它用于不同的目的。 它由head和tail组成。这构成了像Erlang这样的语言的Recursion的基础,它不支持像while / for这样的循环结构。

上面列出的是18 尾巴是剩下的部分:18.01,18.02,18.03,18.04,18.05,18.06

Sunset = [ 18 |  18.01,18.02,18.03,18.04,18.05,18.06] # i.e [ A | B,C] = [A,B,C]

打印每个元素的示例程序:

SunsetFunction([]) -> ok;
SunsetFunction([H|T) -> 
    io:format("~p ~p",H), 
    SunsetFunction(T).

列表可以包含任何数据类型:

[Atom,{Tuple,Var},List]  eg. ['hello@rahul',{rahul,Coder},[20,30,40]]