12

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

非常感谢您的想法。:)

4

7 回答 7

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

当元组没有元素时,它将按预期工作,因为 lists:seq(1,0) 给出了一个空列表。

于 2013-04-25T19:08:15.470 回答
8

您的代码很好,而且是如何制作这种东西的惯用方式。您也可以向后构建此列表,在这种情况下,由于尾调用,它会更快一些,但并不重要。

tup2list(T) -> tup2list(T, size(T), []).

tup2list(T, 0, Acc) -> Acc;
tup2list(T, N, Acc) -> tup2list(T, N-1, [element(N,T)|Acc]).
于 2013-04-25T21:02:25.720 回答
3

我正在尝试 Joe Armstrong 书中的练习,这就是我想出的

my_tuple_to_list(Tuple) -> [element(T, Tuple) || T <- lists:seq(1, tuple_size(Tuple))].
于 2015-01-05T23:02:55.067 回答
2

Erlang R16B 中,您还可以像这样使用erlang:delete_element/2函数:

tuple2list({}) -> [];
tuple2list(T) when is_tuple(T) ->
    [element(1, T) | tuple2list(erlang:delete_element(1, T))].
于 2013-04-25T21:53:44.507 回答
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 以确保给出一个元组。

于 2018-10-15T02:38:43.353 回答
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)    
.
于 2014-06-21T15:14:13.343 回答
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))].

于 2014-11-17T16:25:27.033 回答