Rickard
Rickard

Reputation: 1299

Basic Erlang - Alternatives to function calls in guards etc

I'm trying to learn Erlang, coming from a C++/Java background. This forces me to re-think all my methods.

Right now I'm trying to write something that returns the N first elements of a list. Right now it looks like this, although I can't call functions in guards or if expressions. What is the Erlang way of doing this?

take([Xh|Xr],N,Xn) ->
    if
        len(Xn) /= N -> take(Xr,N,app(Xh, Xn));
        len(Xn) == N -> Xn
    end.

I also tried calling the function before, but that didn't work either:

take([Xh|Xr],N,Xn) ->
   G = len(Xn);
    if
        G /= N -> take(Xr,N,app(Xh, Xn));
        G == N -> Xn
    end.

Upvotes: 4

Views: 520

Answers (3)

I GIVE CRAP ANSWERS
I GIVE CRAP ANSWERS

Reputation: 18859

Your approach isn't wrong per se, it just needs a bit of help:

-module(foo).
-compile(export_all).

take([Xh|Xr],N,Xn) ->
    G = length(Xn), %% This line had trouble. Use length/1 and end with , not ;
    if
        G /= N ->
          take(Xr,N,app(Xh, Xn));
        G == N ->
          Xn
    end.

app(X, L) ->
    L ++ [X].

As other people hints, your approach is not very Erlang idiomatic, and the other solutions are far better. Also, look up the source code for lists:split/2

https://github.com/erlang/otp/blob/master/lib/stdlib/src/lists.erl#L1351

Upvotes: 0

Lukas
Lukas

Reputation: 5327

In addition to Fylke's solution, there is also something to be said for a body recursive approach:

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

Upvotes: 4

Fylke
Fylke

Reputation: 1836

Generally with this kind of problems, you need to switch to a recursive way of thinking instead of the iterative approach you're using. Here's what I would do:

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

It's really common for people coming from languages that promote the iterative approach to try and shoehorn that approach into Erlang. The problem is that Erlang doesn't have the primitives for doing it that way since it's a functional language. So you're forced to do it the functional way, and in the end it's often the more elegant approach.

Upvotes: 5

Related Questions