【问题标题】:Difference between a List and a Tuple in ErlangErlang中列表和元组的区别
【发布时间】:2016-06-07 21:23:06
【问题描述】:

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

【问题讨论】:

标签: functional-programming erlang


【解决方案1】:

@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 标记请求,并确保调用进程始终指定自己的 pid:

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

【讨论】:

    【解决方案2】:

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

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

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

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

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

    【讨论】:

      【解决方案3】:

      本质上,两者的用途完全不同。


      元组

      1.语法:{a ,b, c .. z}.

      2.Purpose : 当你想让一些数据以某种模式分组时,你会使用一个元组。

      例如,我需要昨天的日落和日出时间,我更可能在这里使用元组而不是列表、记录、命令等,因为它完全符合要求。

      {sunrise,7.00},{sunset,18.30}
      

      3.模式匹配:元组支持模式匹配。这是它的完成方式

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

      列表

      1.syntax : [a ,b, c .. z].

      2.目的:一般是在需要一些数据的时候使用,共享的本质就是归类。

      例如,我需要最近 7 天的日落时间,我更可能在这里使用列表而不是元组、记录、命令等。

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

      3.模式匹配,递归,操作:列表也支持模式匹配,但我们也将它用于不同的目的。 它由头和尾组成。这构成了像 Erlang 这样的语言中递归的基础,它不支持像 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]]
      

      【讨论】:

        【解决方案4】:

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

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

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

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

        List :可以递归定义一个列表:它可以是空列表 [],也可以是 2 个元素的构造,即 Head 和 Tail,其中 head 可以是任何 erlang 术语,尾部是一个列表(我说的只是正确的列表)。当您编写程序时不知道该列表将包含多少术语时,您将使用它。服务器可以在列表中存储已连接客户端的名称。您通常会递归地查看列表,因此元素通常是一致的(名称列表,pid 列表......)或使用元组“类型化”,如 proplist 中的。

        这两个元素是更复杂数据结构(如树°

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-10-12
          相关资源
          最近更新 更多