Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erlang - element and list

Tags:

list

erlang

I'm new to erlang. I wonder how to write a function which returns the first N elements in a list?

I've tried:

    take([],_) -> [];
    take([H|T],N) when N > 0 -> take([H,hd(L)|tl(T)], N-1);
    take([H|T],N) when N == 0 -> ... (I'm stuck here...)

Any hint? thx

Update: I know there's a function called "sublist" but I need to figure out how to write that function by my own.

I finally figured out the answer:

-module(list).
-export([take/2]).

take(List,N) -> take(List,N,[]).
take([],_,[]) -> [];
take([],_,List) -> List;
take([H|T], N, List) when N > 0 -> take(T, N-1, lists:append(List,[H]));
take([H|T], N, List) when N == 0 -> List.
like image 531
Ferry Avatar asked Nov 28 '22 02:11

Ferry


2 Answers

In Erlang, take is spelled lists:sublist:

L = [1, 2, 3, 4];
lists:sublist(L, 3).   % -> [1, 2, 3]
like image 87
Warren Young Avatar answered Nov 29 '22 16:11

Warren Young


A simple solution is:

take([H|T], N) when N > 0 ->
    [H|take(T, N-1)];
take(_, 0) -> [].

This will generate an error if there are not enough elements in the list.

When you use an accumulator as you are doing you do not usually append elements to the end of it as this is very inefficient (you copy the whole list each time). You would normally push elements on to it with [H|List]. It will then be in the reverse order but you then do a lists:reverse(List) to return them in the right order.

take(List, N) -> take(List, N, []).

take([H|T], N, Acc) when N > 0 ->
    take(T, N-1, [H|Acc]);
take(_, 0, Acc) -> lists:reverse(Acc).

The accumulator version is tail recursive which is a Good Thing but you need to do an extra reverse which removes some of the benefits. The first version I think is clearer. There is no clear case for either.

like image 23
rvirding Avatar answered Nov 29 '22 16:11

rvirding