Erlang:优雅的tuple_to_list / 1

时间:2013-04-25 17:23:42

标签: functional-programming erlang

我正在通过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)].

非常感谢你的想法。 :)

7 个答案:

答案 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))].