我正在通过Armstrongs“Erlang编程”向Erlang介绍。一个练习是编写tuple_to_list / 1 BIF的重新实现。我的解决方案对我来说似乎相当不优雅,特别是因为我使用的辅助功能。是否有更多的Erlang-ish方法呢?
tup2lis({}) -> [];
tup2lis(T) -> tup2list_help(T,1,tuple_size(T)).
tup2list_help(T,Size,Size) -> [element(Size,T)];
tup2list_help(T,Pos,Size) -> [element(Pos,T)|tup2list_help(T,Pos+1,Size)].
非常感谢你的想法。 :)
答案 0 :(得分:19)
我认为你的功能还可以,如果你的目标是学习语言,那就更多了。 作为一种风格,通常构造列表时的基本情况只是空列表[]。 所以我写了
tup2list(Tuple) -> tup2list(Tuple, 1, tuple_size(Tuple)).
tup2list(Tuple, Pos, Size) when Pos =< Size ->
[element(Pos,Tuple) | tup2list(Tuple, Pos+1, Size)];
tup2list(_Tuple,_Pos,_Size) -> [].
你可以用列表理解来编写相同的内容
[element(I,Tuple) || I <- lists:seq(1,tuple_size(Tuple))].
当元组没有元素时,它将按预期工作,如列表:seq(1,0)给出一个空列表。
答案 1 :(得分:8)
你的代码很好,也是如何制作这类东西的惯用方法。您也可以向后构建此列表,在这种情况下,由于尾调用而不是很重要,因此会更快一些。
tup2list(T) -> tup2list(T, size(T), []).
tup2list(T, 0, Acc) -> Acc;
tup2list(T, N, Acc) -> tup2list(T, N-1, [element(N,T)|Acc]).
答案 2 :(得分:3)
我正在尝试从Joe Armstrong的书中练习,这是我想出来的
my_tuple_to_list(Tuple) -> [element(T, Tuple) || T <- lists:seq(1, tuple_size(Tuple))].
答案 3 :(得分:2)
在Erlang R16B中,您还可以使用erlang:delete_element/2这样的功能:
tuple2list({}) -> [];
tuple2list(T) when is_tuple(T) ->
[element(1, T) | tuple2list(erlang:delete_element(1, T))].
答案 4 :(得分:1)
足够奇怪的是,我现在正在使用第二版的Joe Armstrong的同一本书来学习此知识,而第4章是关于模块和函数的知识,涵盖了列表理解,警卫,累加器等。无论如何,我的解决方案是下面的代码:
-module(my_tuple_to_list).
-export([convert/1]).
convert(T) when is_tuple(T) -> [element(Pos,T) || Pos <- lists:seq(1,tuple_size(T))].
大多数答案已经以相同的方式给出,我只是添加了Guard来确保给出元组。
答案 5 :(得分:0)
Erlang 17.0,您应该按照自然顺序构建列表,从效率的角度来看,上述解决方案是不正确的。始终将元素添加到现有列表的开头:
%% ====================================================================
%% API functions
%% ====================================================================
my_tuple_to_list({}) ->
[];
my_tuple_to_list(Tuple) ->
tuple_to_list_iter(1, size(Tuple), Tuple, [])
.
%% ====================================================================
%% Internal functions
%% ====================================================================
tuple_to_list_iter(N, N, Tuple, List) ->
lists:reverse([element(N, Tuple)|List]);
tuple_to_list_iter(N, Tuplesize, Tuple, List) ->
L = [element(N, Tuple)|List],
tuple_to_list_iter(N + 1, Tuplesize, Tuple, L)
.
答案 6 :(得分:0)
mytuple_to_list(T) when tuple_size(T) =:= 0 -> [];
mytuple_to_list(T) -> [element(1, T)|mytuple_to_list(erlang:delete_element(1, T))].