Overuse of guards in Erlang? - erlang

I have the following function that takes a number like 5 and creates a list of all the numbers from 1 to that number so create(5). returns [1,2,3,4,5].
I have over used guards I think and was wondering if there is a better way to write the following:
create(N) ->
create(1, N).
create(N,M) when N =:= M ->
[N];
create(N,M) when N < M ->
[N] ++ create(N + 1, M).

The guard for N < M can be useful. In general, you don't need a guard for equality; you can use pattern-matching.
create(N) -> create(1, N).
create(M, M) -> [M];
create(N, M) when N < M -> [N | create(N + 1, M)].
You also generally want to write functions so they are tail-recursive, in which the general idiom is to write to the head and then reverse at the end.
create(N) -> create(1, N, []).
create(M, M, Acc) -> lists:reverse([M | Acc]);
create(N, M, Acc) when N < M -> create(N + 1, M, [N | Acc]).
(Of course, with this specific example, you can alternatively build the results in the reverse order going down to 1 instead of up to M, which would make the lists:reverse call unnecessary.)
If create/2 (or create/3) is not exported and you put an appropriate guard on create/1, the extra N < M guard might be overkill. I generally only check on the exported functions and trust my own internal functions.

create(N,N) -> [N];
create(N,M) -> [N|create(N + 1, M)]. % Don't use ++ to prefix a single element.
This isn't quite the same (you could supply -5), but it behaves the same if you supply meaningful inputs. I wouldn't bother with the extra check anyway, since the process will crash very quickly either way.
BTW, you have a recursion depth problem with the code as-is. This will fix it:
create(N) ->
create(1, N, []).
create(N, N, Acc) -> [N|Acc];
create(N, M, Acc) -> create(N, M - 1, [M|Acc]).

I don't really think you have over used guards. There are two cases:
The first is the explicit equality test in the first clause of create/2
create(N, M) when N =:= M -> [M];
Some have suggested transforming this to use pattern matching like
create(N, N) -> [N];
In this case it makes no difference as the compiler internally transforms the pattern matching version to what you have written. You can safely pick which version you think feels best in each case.
In the second case you need some form of sanity check that the value of the argument in the range you expect it to be. Doing in every loop is unnecessary and I would move it to an equivalent test in create/1:
create(M) when M > 1 -> create(1, M).
If you want to use an accumulator I would personally use the count version as it saves reversing the list at the end. If the list is not long I think the difference is very small and you can pick the version which feels most clear to you. Anyway, it is very easy to change later if you find it to be critical.

Related

Applying function repeatedly to generate List

I currently have this f# function
let collatz' n =
match n with
| n when n <= 0 -> failwith "collatz' :n is zero or less"
| n when even n = true -> n / 2
| n when even n = false -> 3 * n + 1
Any tips for solving the following problem in F#?
As said in the comments, you need to give a bit more information for any really specific advice, but based on what you have I'll add the following.
The function you have declared satisfies the definition of the Collatz function i.e. even numbers -> n/2 ,and
odd number -> 3n + 1.
So really you only need applyN, let's break it down into its pieces
( `a -> `a) -> `a -> int -> `a list
applyN f n N
That definition is showing you exactly what the function expects.
lets look at f through to N
f -> a function that takes some value of type 'a (in your case likely int) and produces a new value of type 'a.
This corresponds to the function you have already written collatz`
n -> is your seed value. I don't think elaboration is required.
N -> This looks like a maximum amount of steps to go through. In the example posted, if N was larger, you would see a loop [ 1 ;4; 2; 1; 4... ]
and if it was smaller it would stop sooner.
So that is what the function takes and need to do, so how can we achieve this?
I would suggest making use of scan.
The scan function is much like fold, but it returns each interim state in a list.
Another option would be making use of Seq.unfold and then only taking the first few values.
Now, I could continue and give some source code, but I think you should try yourself for now.

What is the canonical way to handle conditionals in Erlang?

I am working on simple list functions in Erlang to learn the syntax.
Everything was looking very similar to code I wrote for the Prolog version of these functions until I got to an implementation of 'intersection'.
The cleanest solution I could come up with:
myIntersection([],_) -> [];
myIntersection([X|Xs],Ys) ->
UseFirst = myMember(X,Ys),
myIntersection(UseFirst,X,Xs,Ys).
myIntersection(true,X,Xs,Ys) ->
[X|myIntersection(Xs,Ys)];
myIntersection(_,_,Xs,Ys) ->
myIntersection(Xs,Ys).
To me, this feels slightly like a hack. Is there a more canonical way to handle this? By 'canonical', I mean an implementation true to the spirit of what Erlang's design.
Note: the essence of this question is conditional handling of user-defined predicate functions. I am not asking for someone to point me to a library function. Thanks!
I like this one:
inter(L1,L2) -> inter(lists:sort(L1),lists:sort(L2),[]).
inter([H1|T1],[H1|T2],Acc) -> inter(T1,T2,[H1|Acc]);
inter([H1|T1],[H2|T2],Acc) when H1 < H2 -> inter(T1,[H2|T2],Acc);
inter([H1|T1],[_|T2],Acc) -> inter([H1|T1],T2,Acc);
inter([],_,Acc) -> Acc;
inter(_,_,Acc) -> Acc.
it gives the exact intersection:
inter("abcd","efgh") -> []
inter("abcd","efagh") -> "a"
inter("abcd","efagah") -> "a"
inter("agbacd","eafagha") -> "aag"
if you want that a value appears only once, simply replace one of the lists:sort/1 function by lists:usort/1
Edit
As #9000 says, one clause is useless:
inter(L1,L2) -> inter(lists:sort(L1),lists:sort(L2),[]).
inter([H1|T1],[H1|T2],Acc) -> inter(T1,T2,[H1|Acc]);
inter([H1|T1],[H2|T2],Acc) when H1 < H2 -> inter(T1,[H2|T2],Acc);
inter([H1|T1],[_|T2],Acc) -> inter([H1|T1],T2,Acc);
inter(_,_,Acc) -> Acc.
gives the same result, and
inter(L1,L2) -> inter(lists:usort(L1),lists:sort(L2),[]).
inter([H1|T1],[H1|T2],Acc) -> inter(T1,T2,[H1|Acc]);
inter([H1|T1],[H2|T2],Acc) when H1 < H2 -> inter(T1,[H2|T2],Acc);
inter([H1|T1],[_|T2],Acc) -> inter([H1|T1],T2,Acc);
inter(_,_,Acc) -> Acc.
removes any duplicate in the output.
If you know that there are no duplicate values in the input list, I think that
inter(L1,L2) -> [X || X <- L1, Y <- L2, X == Y].
is the shorter code solution but much slower (1 second to evaluate the intersection of 2 lists of 10 000 elements compare to 16ms for the previous solution, and an O(2) complexity comparable to #David Varela proposal; the ratio is 70s compare to 280ms with 2 lists of 100 000 elements!, an I guess there is a very high risk to run out of memory with bigger lists)
The canonical way ("canonical" as in "SICP") is to use an accumulator.
myIntersection(A, B) -> myIntersectionInner(A, B, []).
myIntersectionInner([], _, Acc) -> Acc;
myIntersectionInner(_, [], Acc) -> Acc;
myIntersectionInner([A|As], B, Acc) ->
case myMember(A, Bs) of
true ->
myIntersectionInner(As, Bs, [A|Acc]);
false ->
myIntersectionInner(As, Bs, [Acc]);
end.
This implementation of course produces duplicates if duplicates are present in both inputs. This can be fixed at the expense of calling myMember(A, Acc) and only appending A is the result is negative.
My apologies for the approximate syntax.
Although I appreciate the efficient implementations suggested, my intention was to better understand Erlang's implementation. As a beginner, I think #7stud's comment, particularly http://erlang.org/pipermail/erlang-questions/2009-December/048101.html, was the most illuminating. In essence, 'case' and pattern matching in functions use the same mechanism under the hood, although functions should be preferred for clarity.
In a real system, I would go with one of #Pascal's implementations; depending on whether 'intersect' did any heavy lifting.

f# remove from own user defined list

I want to create a function that removes any occurrence of a integer n and returns the list. I know how I want to do it but do not know the command to delete it.
Here is the data type
type alist =
A
| L of int * Alist
Here's how the data type looks:
let l = L(2, L(1, L(2, L(7, L(3, L(2, A))))))
remove 2 l;;
should return
l = L(1, L(7, L(3, A)))
Here is what I have so far:
let rec remove n l =
match (n, l) with
| (n, A) -> l
| (n, L(head,tail)) when (n = head) ->
I don't know how the how to get rid of a list or element.
You shouldn't be thinking in terms of "deleting" the list; you should instead think in terms of building a new list, without the element you want removed. I'll show you how to do that in a minute, but first I want to make a suggestion. In your match expression, you are re-using the name n in your patterns. That's a classic beginner's mistake, because it ends up confusing you. Once you know F# pretty well, that's a valid technique, but since you appear to be a beginner, I strongly suggest not doing that. Instead, use a name in your patterns that is different from the name of the thing you're matching against, because that will help teach you something. Let's rewrite your match expression with x as the name of the int in your patterns:
let rec remove n l =
match (n, l) with
| (x, A) -> l
| (x, L(head,tail)) when (x = head) ->
What each of these two patterns is doing is assigning the name x to represent the value of n if the rest of the pattern matches. Now we can more clearly see that the first pattern doesn't use the value of x at all, so it would be better to represent it by _ in that case (_ is the "wildcard" pattern, which means "I don't care about the value in this position). Thus, your match expression would become:
let rec remove n l =
match (n, l) with
| (_, A) -> l
| (x, L(head,tail)) when (x = head) -> // ... Still need to write this
Now let's think about what we want to do in that second match case. Here we have a node that is precisely the kind of node we want to remove from the list. So how do we go about building a list without that node in it? Well, as it happens, we already have such a list... and we've assigned it the name tail in that second match case. So at first, it might look like we could just do this:
let rec remove n l =
match (n, l) with
| (_, A) -> l
| (x, L(head,tail)) when (x = head) -> tail
This will return a list with the "head" node chopped off. But wait! What if the tail itself contained one or more nodes with the value we want removed? What we'd really like to return from this match case is tail, passed through a function that would remove all the nodes that match a certain value. But... wait a minute... aren't we writing a function like that right now? What if we could just call remove on the tail and have it do the rest of the work for us; wouldn't that be nice?
Well, it turns out that we can! All you have to do to remove the rest of the unwanted values from the tail list is to call remove on it! Like so:
let rec remove n l =
match (n, l) with
| (_, A) -> l
| (x, L(head,tail)) when (x = head) -> remove n tail
But we're not quite done yet, because there's one more possibility in your match statement. If you are using a good F# development environment (I recommend Visual Studio Code with the Ionide plugin), you should see a green wavy underline under the match keyword, and if you hover over it you should see a warning about an incomplete match expression. That's because there's one case we haven't accounted for: the case where l is a node that isn't A, but whose head value isn't equal to n. In other words, this match case:
| (x, L(head,tail)) when (x <> head) -> // What do we do here?
Well, for starters, let's simplify this match case a bit. If we put it into the complete match expression, we should see that the when guard is actually unnecessary. Match cases are checked from top to bottom, in order. Which means that if we get to the third match case, we already know that x must not be equal to head; otherwise the second match case would have been chosen! You may not be able to see why just yet, so let's put that match case into our match expression and take a look at it:
let rec remove n l =
match (n, l) with
| (_, A) -> l
| (x, L(head,tail)) when (x = head) -> remove n tail
| (x, L(head,tail)) when (x <> head) -> // What do we do here?
Now it's more obvious that this exactly like the previous match case, but with the opposite when guard. Which means that if we ever reach the third match case, the when expression must be true -- because if it was false, then that means that x is equal to head and so we would have gone down the second match case, not the third.
Therefore, we can actually remove the when guard from the third match case, which will now look like this:
let rec remove n l =
match (n, l) with
| (_, A) -> l
| (x, L(head,tail)) when (x = head) -> remove n tail
| (x, L(head,tail)) -> // What do we do here?
There's more simplification that can be done here, but it's time to look at what result we want to return. Here, we do NOT want to skip the first node of the list, but we'd still like to remove n from the tail. In fact, what we want as a result of this function is a list node containing the same head as our current list node, but with a tail that has had n removed from it. (If you don't understand that last sentence, take a minute and try to picture this in your head.) So how do we do this? Well, the simplest way is as follows:
let newTail = remove n tail
L(head, newTail)
Which can be simplified to:
L(head, remove n tail)
So the match function looks like this now:
let rec remove n l =
match (n, l) with
| (_, A) -> l
| (x, L(head,tail)) when (x = head) -> remove n tail
| (x, L(head,tail)) -> L(head, remove n tail)
Believe it or not, we're done! Well, almost: we have a working function now, but it's actually more complicated than it needs to be. Antoine de Saint-Exupéry is most well-known for writing The Little Prince, but he was also an aviator, who has a famous quote about design:
Il semble que la perfection soit atteinte non quand il n'y a plus rien à ajouter, mais quand il n'y a plus rien à retrancher.
In English, that's:
It seems that perfection is attained not when there is nothing more to add, but when there is nothing more to remove.
So what can we remove from this function to pare it down to the absolute essentials? Well, let's start by looking at that last match case again:
| (x, L(head,tail)) -> L(head, remove n tail)
It looks like we don't use the value of x anywhere in this match case, so we don't actually need to assign a name to the int in this match case. We can just use the wildcard _ here. Once we do, our function looks like:
let rec remove n l =
match (n, l) with
| (_, A) -> l
| (x, L(head,tail)) when (x = head) -> remove n tail
| (_, L(head,tail)) -> L(head, remove n tail)
And at this point, you might think that we're really done, because we do use the value of x in the second match case, so we can't get rid of it. Or... can we? Let's look at the second match case more closely:
| (x, L(head,tail)) when (x = head) -> remove n tail
Now. The value of x here is the same as the value of n, because this match case is actually assigning the value of n to the name x by virtue of x being in the first tuple position. Right? So in the when guard, we could actually swap out x for n in the x = head check. This is legal: the checks that you do in a match case do NOT have to include only names that have appeared in the match pattern. They can be any names that your function has access to. So it's perfectly valid to swap x out for n and get the match case to look like this:
| (x, L(head,tail)) when (n = head) -> remove n tail
And now we see that we're not using the value of x in this match case either, just like in the third match case. So let's get rid of it:
| (_, L(head,tail)) when (n = head) -> remove n tail
Now let's put this match case back into our function and take a look at the function as a whole:
let rec remove n l =
match (n, l) with
| (_, A) -> l
| (_, L(head,tail)) when (n = head) -> remove n tail
| (_, L(head,tail)) -> L(head, remove n tail)
Huh. Would you look at that? The first tuple item has "I don't care" in every single spot in the match case. And yet, the function still compiles without warning about incomplete match patterns, and still runs and produces the correct values. (Try it!) So what does this tell us? It tells us that we don't actually need to have n in the value we're matching against, because we never need it in the match patterns. We need it in the when guards, but not in the match patterns themselves! So if we actually remove n from the value we're matching against, and from the match patterns, here's the result:
let rec remove n l =
match l with
| A -> l
| L(head,tail) when (n = head) -> remove n tail
| L(head,tail) -> L(head, remove n tail)
Try it. You'll see that this function also compiles, and still does exactly what you want it to do.
At this point, we really are done. Taking away anything else from this function would break it: either it wouldn't compile, or else it wouldn't return the right value. This may not be immediately obvious to you, but as your skill with F# grows, you'll learn to get a feel for when a function has been pared down to its bare essentials, and this one has.
And so there you go: after a lot of tweaking, we've gotten the remove function not just working, but working elegantly. This is the simplest you can possibly make this function, and there's a certain beauty in that. If you can see and appreciate that beauty, the beauty of a function that does exactly what it should and no more, you'll be well on your way to becoming a skilled F# programmer!
P.S. There is actually one more rewrite that we could do on this function, because it actually could be better. As it stands, this function is not always tail-recursive, which means that if you called it on a really large list, you could get a StackOverflowException. But if you haven't reached the point of studying tail recursion yet, then trying to explain how to fix this problem would be like to confuse you rather than help you understand things better. So I've deliberately chosen to end with this pared-down, elegant version of the function, rather than the version that does tail recursion "properly". Because making that improvement would produce a function that was actually more complicated and harder to understand. Once you're more experienced with F#, it'll be worth revisiting this question and asking "How do I make this function tail-recursive?". But for now, the non-tail-recursive version that we have here is the one that you should study. Once you understand how to write this function on your own, and can write other list-manipulation functions on your user-defined list data structure, then you'll have the knowledge needed to make that last improvement.
I hope this helps. Please leave a comment asking me about anything you don't understand in my explanation.

Counting down from N to 1

I'm trying to create a list and print it out, counting down from N to 1. This is my attempt:
%% Create a list counting down from N to 1 %%
-module(list).
-export([create_list/1]).
create_list(N) when length(N)<hd(N) ->
lists:append([N],lists:last([N])-1),
create_list(lists:last([N])-1);
create_list(N) ->
N.
This works when N is 1, but otherwise I get this error:
172> list:create_list([2]).
** exception error: an error occurred when evaluating an arithmetic expression
in function list:create_list/1 (list.erl, line 6)
Any help would be appreciated.
You should generally avoid using append or ++, which is the same thing, when building lists. They both add elements to the end of a list which entails making a copy of the list every time. Sometimes it is practical but it is always faster to work at the front of the list.
It is a bit unclear in which order you wanted the list so here are two alternatives:
create_up(N) when N>=1 -> create_up(1, N). %Create the list
create_up(N, N) -> [N];
create_up(I, N) ->
[I|create_up(I+1, N)].
create_down(N) when N>1 -> %Add guard test for safety
[N|create_down(N-1)];
create_down(1) -> [1].
Neither of these are tail-recursive. While tail-recursion is nice it doesn't always give as much as you would think, especially when you need to call a reverse to get the list in the right order. See Erlang myths for more information.
The error is lists:last([N])-1. Since N is an array as your input, lists:last([N]) will return N itself. Not a number you expect. And if you see the warning when compiling your code, there is another bug: lists:append will not append the element into N itself, but in the return value. In functional programming, the value of a variable cannot be changed.
Here's my implementation:
create_list(N) ->
create_list_iter(N, []).
create_list_iter(N, Acc) ->
case N > 0 of
true -> NewAcc = lists:append(Acc, [N]),
create_list_iter(N-1, NewAcc);
false -> Acc
end.
If I correctly understand your question, here is what you'll need
create_list(N) when N > 0 ->
create_list(N, []).
create_list(1, Acc) ->
lists:reverse([1 | Acc]);
create_list(N, Acc) ->
create_list(N - 1, [N | Acc]).
If you work with lists, I'd suggest you to use tail recursion and lists construction syntax.
Also, to simplify your code - try to use pattern matching in function declarations, instead of case expressions
P.S.
The other, perhaps, most simple solution is:
create_list(N) when N > 0 ->
lists:reverse(lists:seq(1,N)).

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

Resources