【发布时间】:2016-06-07 21:23:06
【问题描述】:
Erlang 中列表和元组的主要区别是什么。模式匹配如何区分每个。?
【问题讨论】:
-
希望此链接回答您的部分问题,erlang.org/pipermail/erlang-questions/2007-September/…
标签: functional-programming erlang
Erlang 中列表和元组的主要区别是什么。模式匹配如何区分每个。?
【问题讨论】:
标签: functional-programming erlang
@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.
【讨论】:
它们是不同的数据类型,具有不同的实现和操作成本:
元组,通常用于表示固定数量可能不同类型的值的集合,您希望能够在恒定时间内访问任何值。它们还用于在不使用异常的情况下区分正常返回(例如{ok, Value})和错误返回(例如error)。
列表,通常用于表示任意数量相同类型值的集合,您希望能够以迭代方式处理元素(例如,使用map 或fold 操作)。
匹配元组(例如{A,B,C})的模式,通常匹配特定大小的元组和/或某些元素的特定值。
匹配列表的模式(例如[H|T]),通常匹配第一个和其余元素。
【讨论】:
本质上,两者的用途完全不同。
元组
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]]
【讨论】:
我将尝试回答何时使用元组或列表。它们都是 erlang 术语的集合,并且由于它们不像任何其他 erlang 变量那样可变,因此差异不是固定大小。
元组:当您在编写程序时知道元组将包含多少个术语,当所有术语都具有特殊含义并且您将能够使用它们访问它们时,您将使用元组位置。一个很好的例子可以是点 P={X,Y,Z} 的坐标。
当您认为您的应用程序的未来发展可能会在集合中引入新术语时,您可能会选择一条记录:具有某种语法工具的命名元组可以按名称访问每个元素,示例是代表员工的记录(姓名、地址、出生、代码、技能列表)也许您稍后会添加电话号码、电子邮件...
一个常见的用法是返回多个值或标记值({ok,Value}, {error,Reason})。
List :可以递归定义一个列表:它可以是空列表 [],也可以是 2 个元素的构造,即 Head 和 Tail,其中 head 可以是任何 erlang 术语,尾部是一个列表(我说的只是正确的列表)。当您编写程序时不知道该列表将包含多少术语时,您将使用它。服务器可以在列表中存储已连接客户端的名称。您通常会递归地查看列表,因此元素通常是一致的(名称列表,pid 列表......)或使用元组“类型化”,如 proplist 中的。
这两个元素是更复杂数据结构(如树°
【讨论】: