Pattern match in Erlang - erlang

I am trying to learn some Erlang while I got stuck on these several Erlang pattern matching problems.
Given the module here:
-module(p1).
-export([f2/1]).
f2([A1, A2 | A1]) -> {A2, A1};
f2([A, true | B]) -> {A, B};
f2([A1, A2 | _]) -> {A1,A2};
f2([_|B]) -> [B];
f2([A]) -> {A};
f2(_) -> nothing_matched.
and when I execute p1:f2([x]), I received an empty list which is []. I thought it matches the 5th clause? Is that a literal can also be an atom?
When I execute p1:f2([[a],[b], a]), the result is ([b], [a]) which means it matches the first clause. However I think [a] and a are not the same thing? One is a list but the other is a literal?
Also when I execute p1:f2([2, 7 div 3 > 2 | [5,3]]) it evaluates to (2, false). I mean why 7 div 3 > 2 gets to be false? In other language such as C or Java Yeah I know 7 div 3 == 2 so it makes this statement false. But is it the same in Erlang? Because I just tried it on shell and it gives me 2.3333333.. which is larger than 2 so it will make this statement true. Can someone gives an explaination?

it is because [x] is equal to [x|[]] so it matches f2([_|B]) -> [B];. As you can see B=[] inn your case.
I think you didn't write what you want to do. in the expression [A|B], A is the first element of the list, while B is the rest of the list (so it is a list). That means that [1,2,1] will not match [A1, A2 | A1]; but [[1],2,1] or [[a,b],1,a,b] will.

First, 7 div 3 is 2. And 2 is not greater than 2, it's equal.
Secondly, [x, y] = [x | [y] ], because the right (or rest) part is always a list. That's why you get in the first clause.

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.

F# how to mirror a binary tree

New to F#
I am trying to flip the sub trees on the branches.
we must use the following data types
type btree = Empty | Node of btree * int * btree
type finding = NotFound | Found of int
example tree
let s = Node (Node(Empty, 5, Node(Empty, 2, Empty)), 3, Node (Empty, 6, Empty))
(*
(3)
/ \
(5) (6)
/ \ | \
() (2) () ()
/ \
() ()
*)
here is my code so far:
let rec mirror t = function
| Node(Empty, t, Empty) -> t
| Node (t1, t, t2) ->
| _ -> failwith "Empty"
example input and output:
mirror (Node (Node (Empty, 1, Empty), 3, Node (Empty, 4, Node (Empty, 7, Empty)))
would return
Node (Node (Node (Empty, 7, Empty), 4, Empty), 3, Node (Empty, 1, Empty))
Right now the code doesn't accomplish anything, I am needing help on how I would move a nodes around to get the mirrored tree that I want.
I wonder if I must implement another function for deleting/inserting nodes? Any help is greatly appreciated!
This seems like homework, so I'll add a few learning points, before I 'hand over' the solution. Let's have a look at the code you have written already, which is not a terrible start. I have pasted it below for reference.
let rec mirror t = function
| Node(Empty, t, Empty) -> t
| Node (t1, t, t2) ->
| _ -> failwith "Empty"
You start off with allowing your function to call itself recursively, by adding the rec keyword. You are right to do that, and it's actually a pretty important realisation, that the way to go about this task, is to create a recursive function. Because, really, what does it mean to 'mirror' a tree? Mirroring means, at each node, flip the order of the subtrees, and mirror each subtree.
This is a recursive definition, since to mirror a node, you need to mirror the subtrees. So you're right about adding the rec keyword. However, in your code, you don't properly handle the terminal state Empty. Using your btree definition, you will eventually see an Empty tree, which means you will eventually throw an exception (using the failwith). This is obviously not the desired behaviour. What does the mirror of an empty tree look like? Empty! The way to handle this case, is then to replace | _ -> failwith "Empty" with | Empty -> Empty.
Now, in F#, let foo = function | ... is just syntactic sugar for let foo <arg> = match <arg> with | ..., which means your function actually takes two parameters: t and one which is hidden by the function sugar. I suppose this is not what you want, so you should either remove the currently unused parameter t, or replace function with match t with.
The reason the parameter t is currently unused, is that t is rebound to the integer node-value in the match-cases | Node(..., t, ...). This also means that the compilers current best guess, is probably that the return type of mirror should be int, rather than btree, since you return an int in the first case.
One last point is that there is no reason for handling the case with empty subtrees directly, since these are also just btrees.
Keeping all of the above in mind, I hope it makes sense why my solution to the problem is
let rec mirror = function
| Empty -> Empty
| Node(t1, i, t2) -> Node(mirror t2, i, mirror t1)
Mirroring means making the left branch the right branch and the right branch the left branch. So in your recursive function do that. For example if you start with a basic 3 node tree:
1
2 3
then mirroring that will be
1
3 2
So in code that means:
let rec mirror t = function
| Node(Empty, t, Empty) -> t
| Node (left, value, right) -> Node (right, value, left)
Except that won't work for larger trees, but it's a start. What you really want is the mirror of the right and left nodes as well. You should be able to complete the function above by adding 2 calls to mirror in the correct place in the last line of the match clause.

Erlang pattern matching error

I have started learning Erlang recently and came across the following error while trying to pattren match
The following expression is working fine:
{A,_,[B|_],{B}}={abc,23,[22,x],{22}}.
Resulting in
A = abc
B = 22
The following expression is not working:
{A,_,[_|B],{B}}={abc,23,[22,x],{x}}.
Is resulting in
** exception error: no match of right hand side value {abc,23,[22,x],{x}}
However if I replace the ',' in [22 , x with a | like the following its working find and bounding x to B
{A,_,[_|B],{B}}={abc,23,[22|x],{x}}.
{abc,23,[22|x],{x}}
B.
x
Any explanation about this would highly appreciated.
Many thanks in advance
The operator | is used for a recursive definition of a list: [A|B] means that you add the element A to an existing list B. A is the first element of the resulting list, called the head, B is the rest of the list called tail. B can be also split into a head and a tail, and the process can continue until the tail is equal to the empty list [].
The operator , is a separator between list elements, so [A,B] is a list of 2 elements A and B.
The 2 operators can be combined: [A,B,C|D] is a list of at least 3 elements, which are A, B and C, and a tail D which can be empty.
In your test you used another syntax: [23|x]; 23 can be an element of a list (in fact any erlang term can be an element of a list) but x is an atom and cannot be a list tail. Doing this you broke the recursive definition of the list, this structure is not often used and is called an improper list.
when you match [_|B] and [_,x], you assign [x] to B which do not match to x later in the expression
when you match [_|B] and [_|x], you assign x to B which indeed match to x later in the expression, but the right way should be
{A,_,[_|B],{B}}={abc,23,[22,x],{[x]}}.
You need to look closer on how does the | operator works. It basically takes head of list, which is one element, and returns tail of list, which is all the rest. And like "all" suggest tail is also a list. It could be one element list, it could be even empty list, but still it's gonna be a list.
> [Head| Tail] = [23,x].
[23,x]
> Head.
23
> Tail
[x].
So in your pattern matching, you assign to be tail [x], and than try to pattern match on simply x. And that's what's failing.
On side note: you can create new list with | operator, but you should do this with caution. since you could create improper list (and you do with [23 | x]). That's why your "fix" is working.
If you would like to match on two element list, you could do it explicitly with
[A, B] = [23, x].
but this will fail if list have more or less elements.
If you would like to match on only on two first elements, you can still use | operator.
> [A, B | Rest] = [23, x].
[23, x]
> A.
23
> B.
x
> Rest.
[].
And this will fail only with one-element or empty list.

how to efficiently build erlang lists in natural order?

In the Programming Erlang book, there is some example pseudo code that shows a pattern for efficiently adding elements to the head of a list:
some_function([H|T], ..., Result, ...) ->
H1 = ... H ...,
some_function(T, ..., [H1|Result], ...);
some_function([H|T], ..., Result, ...) ->
{..., Result, ...}.
I'm still getting used to functional programming so the above example is a little too abstract for me to understand at the moment.
I think it will be easier to understand if there is a concrete implementation of the pattern that I could dissect.
Question: Is there a simple concrete implementation of this pattern that someone can provide?
Let's say that we want a function which behaves a like the uniq command.
The function takes a list of elements and returns a list with all consecutive occurrences of an element substituted with a single occurrence of that element.
One of the possible approaches is presented below:
uniq(L) ->
uniq(L, []).
uniq([], Acc) ->
lists:reverse(Acc);
uniq([H, H | T], Acc) ->
uniq([H | T], Acc);
uniq([H | T], Acc) ->
uniq(T, [H | Acc]).
We build up an accumulator, by inserting new elements at the head of the Acc list (cheapest insertion cost) and once we're done, we reverse the whole list to get the initial order of elements back.
We "visit" some of the elements of the initial list twice, but the total cost is still linear, i.e. only dependent on the number of elements of the initial list.
This takes a factorized list, i.e.
[[],[2],[3],[2,2],[5],[2,3],[7],[2,2,2],etc...]
and removes all the primes.
remove_primes([HD|TL], Results) ->
case length(HD) of
0 -> % You're at 1
remove_primes (TL , Results);
1 -> % Its a prime, remove it, and keep going
remove_primes( TL , Results) ;
_ -> % its not prime, leave it in and keep going.
remove_primes(TL, [ HD | Results])
end;
remove_primes([], Result) ->
{Result}.
The structure Joe Armstrong was alluding too, is the standard structure of walking a list and applying a function to each element on the list. In this case, I desired to treat each element differently depending on its contents.
In practice, it is much easier to to use maps, filters and such, so I believe you will see that much more often - but as you seem to know, understanding the basics is vital to becoming a proficient functional programmer.
In hopes centralize information pertaining to 'building lists in natural order', does anyone know why pattern matching at the function level, works, 'but unpacking' a variable does not? (compare this)(it does not work)
remove_primes(Factorized_List, Results) ->
[HD|TL] = Factorized_List, % unpack the list <-------------
case length(HD) of
0 -> % You're at 1
remove_primes (TL , Results);
1 -> % Its a prime, remove it, and keep going
remove_primes( TL , Results) ;
_ -> % its not prime, leave it in and keep going.
remove_primes(TL, [HD|Results])
end;
remove_primes([], Result) ->
{Result}.
I believe this leads to more readable code, but it does not seem to work.
-rC
Here is the only way I can get your pattern to execute:
some_func([H|T], 4, Result, 4) ->
H1 = H * 2,
some_func(T, 3, [H1|Result], 4);
some_func([H|T], 3, Result, _) ->
{H, Result, T}.
--output:--
25> a:some_func([1, 2, 3], 4, [], 4).
{2,[2],[3]}
...which does nothing useful.
The pattern in the pseudo code makes no sense to me, so I'll join you in your confusion.
Here is another attempt:
some_func([H|T], [_|T2], Result, Y) ->
H1 = H * Y,
some_func(T, T2, [H1|Result], Y);
some_func([H|T], [], Result, _) ->
{H, Result, T}.
--output:--
34> a:some_func([1, 2, 3, 4], [one, two, three], [], 2).
{4,[6,4,2],[]}

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

Resources