Подтвердить что ты не робот

Erlang: элегантный tuple_to_list/1

Я познакомился с Эрланом Армстронгами "Программирование Эрланг". Одно упражнение - написать повторную реализацию 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)].

Большое спасибо за ваши идеи.:)

4b9b3361

Ответ 1

Я думаю, что ваша функция в порядке, и больше, если ваша цель - изучить язык. Как правило, базовый случай при построении списков - это просто пустой список []. Поэтому я напишу

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) дает пустой список.

Ответ 2

Ваш код хорош, а также идиоматический способ сделать такой материал. Вы также можете создать этот список назад, который в этом случае будет немного быстрее из-за хвостового вызова, но не значителен.

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

tup2list(T, 0, Acc) -> Acc;
tup2list(T, N, Acc) -> tup2list(T, N-1, [element(N,T)|Acc]).

Ответ 3

Я пытаюсь выполнить упражнения из книги Джо Армстронга. Вот что я придумал

my_tuple_to_list(Tuple) -> [element(T, Tuple) || T <- lists:seq(1, tuple_size(Tuple))].

Ответ 4

В Erlang R16B вы также можете использовать erlang: delete_element/2, например:

tuple2list({}) -> [];
tuple2list(T) when is_tuple(T) ->
    [element(1, T) | tuple2list(erlang:delete_element(1, T))].

Ответ 5

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

mytuple_to_list(T) when tuple_size(T) =:= 0 -> []; mytuple_to_list(T) -> [element(1, T)|mytuple_to_list(erlang:delete_element(1, T))].