@Arunmu提供的链接回答了问题的第一部分.您可以使用警卫来区分这些数据结构:
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]).
Run Code Online (Sandbox Code Playgroud)
但实际上,你通常以这样的方式设计你的函数,你知道,如果它需要元组或列表并使用模式匹配来获取元素.如果您知道它有多少元素,您可以像这样模式匹配列表:
[A, B, C] = [1, 2, 3] # A becomes 1, B becomes 2, C becomes 3
Run Code Online (Sandbox Code Playgroud)
但通常,您可以利用列表递归性质.每个列表都是:
这是模式匹配,你经常会使用:
[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
Run Code Online (Sandbox Code Playgroud)
因此处理列表的函数通常是递归的:
do_stuff([]) ->
finished; # there are no more elements
do_stuff([H | T]) ->
do_something_with(H),
do_stuff(T).
Run Code Online (Sandbox Code Playgroud)
所以你不必知道列表的长度是多少来处理所有元素.当你使用元组时,你知道它们有多大.典型的模式匹配是:
{A, B} = {lol, rotfl} # A becomes lol, B becomes rotfl
{A, _} = {troll, trololo} # A becomes troll
Run Code Online (Sandbox Code Playgroud)
元组经常用于标记事物.当您收到来自其他进程的消息时,请使用receive
receive
Request -> do_something_with(Request)
end.
Run Code Online (Sandbox Code Playgroud)
但我们不知道,如果请求有效或者某些其他进程错误地发送了某些内容.我们可以使用atom标记Request request并确保调用进程始终指定自己的pid:
receive
{request, Pid, Request} ->
Response = do_something_with(Request),
Pid ! Response;
_ -> ignore_message
end.
Run Code Online (Sandbox Code Playgroud)
它们是不同的数据类型,具有不同的实现和操作成本:
元组,通常用于表示可能不同类型的固定数量值的集合,您希望能够在恒定时间内访问任何值。它们还用于在不使用异常的情况下区分正常返回(例如)和错误返回(例如)。{ok, Value}error
列表,通常用于表示相同类型的任意数量值的集合,您希望能够以迭代方式(例如使用 a或操作)处理元素。mapfold
匹配元组的模式(例如{A,B,C}),通常匹配特定大小的元组和/或某些元素的特定值。
匹配列表的模式(例如[H|T]),通常与 first 和 rest 元素匹配。