2013-04-25 31 views
11

Tôi được giới thiệu về Erlang bởi Armstrongs "Lập trình Erlang". Một bài tập là viết một bản tái xác nhận của tuple_to_list/1 BIF. Giải pháp của tôi có vẻ khá không phù hợp với tôi, đặc biệt là vì chức năng trợ giúp tôi sử dụng. Có một cách Erlang-ish hơn để làm điều này?Erlang: thanh lịch tuple_to_list/1

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

Cảm ơn bạn rất nhiều vì ý tưởng của bạn. :)

+1

Hãy cho mình biết mà của các triển khai bên dưới là đệ quy đuôi. – Tilman

+3

Không có gì sai khi có các hàm trợ giúp, thường bạn cần chúng và chúng là cách tốt nhất để làm việc. Và đừng lo lắng về việc đệ quy đuôi, hãy xem http://www.erlang.org/doc/efficiency_guide/listHandling.html#id64720 – rvirding

Trả lời

17

Tôi nghĩ chức năng của bạn là ok và hơn thế nữa nếu mục tiêu của bạn là học ngôn ngữ. Như một vấn đề về phong cách, thường là trường hợp cơ bản khi xây dựng danh sách chỉ là danh sách rỗng []. Vì vậy, tôi muốn viết

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

bạn có thể viết khá nhiều việc cùng với danh sách hiểu

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

nó sẽ làm việc như mong đợi khi tuple không có các yếu tố, như danh sách: seq (1,0) đưa ra một danh sách trống.

+3

+1 để hiểu danh sách. Tôi thích việc sử dụng danh sách: seq. Cảm thấy một chút pythonian với tôi. ;) – Zakum

7

Mã của bạn tốt và cũng là cách thành ngữ cách tạo loại nội dung này. Bạn cũng có thể xây dựng danh sách này ngược lại trong trường hợp này sẽ nhanh hơn một chút vì cuộc gọi đuôi nhưng không đáng kể.

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

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

Tốt hơn nên sử dụng 'tuple_size/1' thay vì' size/1'. Xem tại đây: http://erlang.org/doc/efficiency_guide/commoncaveats.html – coffeMug

2

Trong Erlang R16B bạn cũng có thể sử dụng chức năng erlang:delete_element/2 như thế này:

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

+1 để loại bỏ chức năng trợ giúp và sự cần thiết của bộ đếm và bộ đếm. Tôi đọc rằng sự tăng tốc độ đệ quy đuôi so với đệ quy đầu trong các phiên bản hiện tại là một vấn đề về kiến ​​trúc bộ vi xử lý * vì vậy tôi bỏ như giải pháp này! * http: //www.erlang.org/doc/efficiency_guide/myths.html – Zakum

+4

-1 cho giải pháp tạo ra một bộ tuple mới khi một phần tử được thêm vào danh sách. Hãy nhớ rằng không có dữ liệu có thể thay đổi trong erlang và 'erlang: delete_element/2' tạo một bộ dữ liệu mới! – rvirding

+0

@Zakum: Bạn nên đọc kỹ phần phân tích huyền thoại này một cách cẩn thận hơn. _body-đệ quy danh sách chức năng và đuôi đệ quy chức năng mà gọi 'danh sách: đảo ngược/1' ở cuối sẽ sử dụng chính xác cùng một lượng bộ nhớ_ Lưu ý các' danh sách: đảo ngược/1' mà tôi phiên bản không làm. Phiên bản đệ quy đuôi của tôi chắc chắn sẽ nhanh hơn đệ quy [ppolv] (http://stackoverflow.com/users/171116/ppolv) của http://stackoverflow.com/users/171116/ppolv) (http://stackoverflow.com/a/16222818/49197), không nghi ngờ gì. Nhưng khi hầu hết các tuple là ti nhỏ không quan trọng. Nhưng biết sự khác biệt. –

0

Erlang 17,0, bạn nên xây dựng danh sách theo thứ tự tự nhiên, các giải pháp trên là không chính xác từ quan điểm hiệu quả. Luôn thêm các yếu tố để người đứng đầu của danh sách hiện:

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

3

Tôi đang cố gắng tập từ Joe Armstrong cuốn sách, đây là những gì tôi đã đưa ra

my_tuple_to_list(Tuple) -> [element(T, Tuple) || T <- lists:seq(1, tuple_size(Tuple))]. 
Các vấn đề liên quan