简体   繁体   中英

Erlang - element and list

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.

In Erlang, take is spelled lists:sublist :

L = [1, 2, 3, 4];
lists:sublist(L, 3).   % -> [1, 2, 3]

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM