Understanding what this Erlang Code is? - erlang

Not at all familiar with Erlang, but am trying to interpret what this code does?
Below is my understanding about the code. Any help will be useful.
I am looking at the tutorials but the passing values are confusing in this case.
example- convert_list_to_k([{Name, {l, Weight}} | Rest]) //{1,Weight} <- This one
And how is the value returned in convert_list_to_k?
let's say for this function block
convert_list_to_k([{Name, {l, Weight}} | Rest]) ->
Converted_Object = {Name, {k, Weight / 0.45359237}},
[Converted_Object | convert_list_to_k(Rest)];
convert_list_to_k([Object | Rest]) ->
[Object | convert_list_to_k(Rest)];
convert_list_to_k([]) ->
[].
Below is the code with explanations.
-module(erlang_program).
-export([format_weight/1]).
in the above export the /1 represents it's going to receive an attribute(I don't know which attribute)
format_weight(List_of_objects) ->
Converted_List = convert_list_to_k(List_of_objects),
print_weight(Converted_List),
{Max_object, Min_object} = find_max_and_min(Converted_List),
print_max_and_min(Max_object, Min_object).
Kind of main function, which will import convert_list_to_k, print_weight(Converted_List),find_max_and_min(Converted_List) and print_max_and_min(Max_object, Min_object).
According to my understanding it's doing the following things:
Converts a list of object to some format
Prints the converted list
Find the Max and Min, and place it in Object Max and Min
Prints the Max and Min Object
I am getting confused by the way [{Name, {l, Weight}} | Rest] is passed
convert_list_to_k([{Name, {l, Weight}} | Rest]) ->
Converted_Object = {Name, {k, Weight / 0.45359237}},
[Converted_Object | convert_list_to_k(Rest)];
convert_list_to_k([Object | Rest]) ->
[Object | convert_list_to_k(Rest)];
convert_list_to_k([]) ->
[].
print_weight([{Name, {k, Weight}} | Rest]) ->
io:format("~-15w ~w c~n", [Name, Weight]),
print_weight(Rest);
print_weight([]) ->
ok.
find_max_and_min([Object | Rest]) ->
find_max_and_min(Rest, Object, Object).
find_max_and_min([{Name, {k, Weight}} | Rest],
{Max_Name, {k, Max_Weight}},
{Min_Name, {k, Min_Weight}}) ->
if
Weight > Max_Weight ->
Max_Object = {Name, {k, Weight}};
true ->
Max_Object = {Max_Name, {k, Max_Weight}}
end,
if
Weight < Min_Weight ->
Min_Object = {Name, {k, Weight}};
true ->
Min_Object = {Min_Name, {k, Min_Weight}}
end,
find_max_and_min(Rest, Max_Object, Min_Object);
find_max_and_min([], Max_Object, Min_Object) ->
{Max_Object, Min_Object}.
print_max_and_min({Max_name, {k, Max_object}}, {Min_name, {k, Min_object}}) ->
io:format("Max weight was ~w c in ~w~n", [Max_object, Max_name]),
io:format("Min weight was ~w c in ~w~n", [Min_object, Min_name]).

Don't worry that this code is a bit confusing. It is somewhat unidiomatic. We'll address that in a moment...
Before style, look at this first function, convert_list_to_k/1. It is selectively converting objects from a form marked with l to a form marked with k.
How is it selecting? It is matching on the shape and value of the first element of the list passed to it as an argument. If it receives a value with an l type value inside like {Name, {l, Weight}} then the first clause is selected and run, which converts the {l, Weight} part to a {k, Weight} value -- I assume here this is "l" for "pounds" and "k" for "kilograms".
This function is doing depth recursion which is not usually a good fit for this particular case, because Erlang (and most functional languages) have an optimization for tail recursion.
foo([Thing | Things]) ->
NewThing = change(Thing),
[NewThing | foo(Things)];
foo([]) ->
[].
This is basically what the function is doing. This means that for whatever size the list is, a new layer of the call stack has to be added because the original list in the first clause cannot be returned without remembering every intermediate value. This will not work on arbitrarily long lists without significant memory overhead and is generally not how things work.
Imagine in memory seeing this:
foo([change(Thing1) | foo([change(Thing2) | foo([change(Thing3) | ...]]])
Not very tidy. Sometimes it is the right thing to do, but not in the general case of iterating over a list.
A tail recursive version would look like this:
foo(Things) ->
foo(Things, []).
foo([Thing | Things], Accumulator) ->
NewThing = change(Thing),
foo(Things, [NewThing | Accumulator]);
foo([], Accumulator) ->
lists:reverse(Accumulator).
This version runs in constant space and is the more idiomatic form of explicit recursion.
So what about all that matching stuff? Well, let's say I wanted to print a value in kilograms every time, but some of my values are in pounds and some are in kilos. I could wrap the raw number values in a tuple and use an atom to tag the values so I know what they mean. For example, a tuple like {pounds, X} would mean I have a number, X, and it is in pounds, or a tuple {kilos, X} which would mean X is kilos. Both are still weight.
So how would my function look?
print_weight({kilos, X}) ->
io:format("Weight is ~wkgs~n", [X]);
print_weight({pounds, X}) ->
Kilos = X / 0.45359237,
io:format("Weight is ~wkgs~n", [Kilos]).
So this function works fine as long as it is passed either kind of tuple.
How about a list of these? We could do explicit recursion like above:
print_weights([{kilos, X} | Rest]) ->
ok = io:format("Weight is ~wkgs~n", [X]),
print_weights(Rest);
print_weight([{pounds, X} | Rest]) ->
Kilos = X / 0.45359237,
ok = io:format("Weight is ~wkgs~n", [Kilos]),
print_weights(Rest);
print_weights([]) ->
ok.
So this handles a list of values like above. But we don't really need to write all that, do we? We already had a function called print_weight/1, and it already knows how to do the matching. What we could do instead is more simply define print_weights/1 as a function that uses a list operation:
print_weights(List) ->
lists:foreach(fun print_weight/1, List).
See, we usually don't do explicit recursion when we can help it. The reason is that in the simple case we already have higher-order functions made to simplify simple iteration over lists. In the case where we want a side effect and don't care about the return value, like printing the weights as above, we use lists:foreach/2.
Going back to the "change" example above, if we already know that we want to perform change/1 on each value, but return the same map back intact, it makes more sense to either use a list comprehension or lists:map/2.
A list comprehension is a special syntax over a map, which can also include guards. The simple case of mapping a function over every value in a list and returning that list looks like this:
ChangedThings = [change(Thing) || Thing <- Things]
A map looks almost exactly the way lists:foreach/2 did above:
ChangedThings = lists:map(fun change/1, Things)
Now, going back to your original example... maybe we want to ensure a specific value type. So we could write a simple function that does only that:
ensure_metric({Name, {l, Pounds}}) ->
Kilos = Pounds / 0.45359237,
{Name, {k, Kilos}};
ensure_metric(Value = {_, {k, _}}) ->
Value.
That's all we need. What is happening above is that any tuple of the form {Foo, {l, Bar}} matches the first clause and gets converted by the operation in that clause and then repacked to a {Foo, {k, Baz} form, and any tuple of the form {Foo, {k, Bar}} matches the second but is passed along without being changed. We can now simply map that function over a list:
convert_list_to_k(List) ->
lists:map(fun ensure_metric/1, List).
Much easier to reason about just one function at a time!
The min/max function is a bit insane. We would not want to write an if unless we had a fully bounded mathematical case. For example:
if
X > Y -> option1();
X =:= Y -> option2();
X == Y -> option3();
X < Y -> option4()
end,
This is four tests in a single clause. Occasionally using an if makes sense for that. More often, though, you wind up with what you had above, where a simple comparison happens. In that case a case is much more expressive:
case X > Y ->
true -> do_something();
false -> something_else()
end,
BUT! Maybe what we really want in a min/max function is to just operate over guards and avoid writing some complex body logic. Here is one that operates over a simple list of numbers, a slight change would make it fit the data type you are dealing with (those tuples):
min_max([Number | Numbers]) ->
min_max(Numbers, Number, Number).
min_max([N | Ns], Min, Max) when N < Min ->
min_max(Ns, N, Max);
min_max([N | Ns], Min, Max) when N > Max ->
min_max(Ns, Min, N);
min_max([_ | Ns], Min, Max) ->
min_max(Ns, Min, Max);
min_max([], Min, Max) ->
{Min, Max}.
Not a whole lot of cheetah flips are needed in procedural logic here.
Erlang is so boringly simple and tiny as a language that once the needlessness of most procedural logic sinks in you just suddenly "get new eyes". A few related Q/As with background information may be helpful on your journey:
Erlang Recursive end loop
How does the recursive call work in this erlang function?
Explanation of lists:fold function
Function chaining in Erlang

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.

Performing Calculations on F# option types

I'm trying to write some function that handle errors by returning double options instead of doubles. Many of these functions call eachother, and so take double options as inputs to output other double options. The problem is, I can't do with double options what I can do with doubles--something simple like add them using '+'.
For example, a function that divides two doubles, and returns a double option with none for divide by zero error. Then another function calls the first function and adds another double option to it.
Please tell me if there is a way to do this, or if I have completely misunderstood the meaning of F# option types.
This is called lifting - you can write function to lift another function over two options:
let liftOpt f o1 o2 =
match (o1, o2) with
| (Some(v1), Some(v2)) -> Some(f v1 v2)
| _ -> None
then you can supply the function to apply e.g.:
let inline addOpt o1 o2 = liftOpt (+) o1 o2
liftA2 as mentioned above will provide a general way to 'lift' any function that works on the double arguments to a function that can work on the double option arguments.
However, in your case, you may have to write special functions yourself to handle the edge cases you mention
let (<+>) a b =
match (a, b) with
| (Some x, Some y) -> Some (x + y)
| (Some x, None) -> Some (x)
| (None, Some x) -> Some (x)
| (None, None) -> None
Note that liftA2 will not put the cases where you want to add None to Some(x) in automatically.
The liftA2 method for divide also needs some special handling, but its structure is generally what we would write ourselves
let (</>) a b =
match (a, b) with
| (Some x, Some y) when y <> 0.0d -> Some (x/y)
| _ -> None
You can use these functions like
Some(2.0) <+> Some(3.0) // will give Some(5.0)
Some(1.0) </> Some(0.0) // will give None
Also, strictly speaking, lift is defined as a "higher order function" - something that takes a function and returns another function.
So it would look something like this:
let liftOpt2 f =
(function a b ->
match (a, b) with
| (Some (a), Some (b)) -> f a b |> Some
| _ -> None)
In the end, I realized what I was really looking for was the Option.get function, which simply takes a 'a option and returns an 'a. That way, I can pattern match, and return the values I want.
In this case you might want to consider Nullables over Options, for two reasons:
Nullables are value types, while Options are reference types. If you have large collections of these doubles, using Nullables will keep the numbers on the stack instead of putting them on the heap, potentially improving your performance.
Microsoft provides a bunch of built-in Nullable Operators that do let you directly perform math on nullables, exactly as you're trying to do with options.

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

How do I turn a list of tuple pairs into a record in Erlang?

Let's say I have this:
-record(my_record, {foo, bar, baz}).
Keyvalpairs = [{foo, val1},
{bar, val2},
{baz, val3}].
Foorecord = #my_record{foo=val1, bar=val2, baz=val3}.
How do I convert Keyvalpairs into Foorecord?
The simplest thing to do is:
Foorecord = #my_record{foo=proplists:get_value(foo, Keyvalpairs),
bar=proplists:get_value(bar, Keyvalpairs),
baz=proplists:get_value(baz, Keyvalpairs)}.
If this is too repetitive you can do something like:
Foorecord = list_to_tuple([my_record|[proplists:get_value(X, Keyvalpairs)
|| X <- record_info(fields, my_record)]]).
Like the other answers point out, you need to roll your own solution to accomplish this. The solutions proposed are however incomplete. For example, it doesn't take into account default values for record entries. I use the following code snippet to take care of this conversion:
%% #doc returns a "RECSPEC" that can be used by to_rec in order to
%% perform conversions
-define(RECSPEC(R), {R, tuple_to_list(#R{}), record_info(fields, R)}).
%% #doc converts a property list into a record.
-spec to_rec(recspec(), proplist()) -> record().
to_rec({R, [_ | N], Spec}, P) when is_atom(R) and is_list(Spec) ->
list_to_tuple(
[R | lists:foldl(
fun ({K,V}, A) ->
case index_of(K, Spec) of
undefined ->
A;
I ->
{Head, Tail} = lists:split(I, A),
Rest = case Tail of
[_ | M] -> M;
[] -> []
end,
Head ++ [V | Rest]
end
end, N, P)]).
Now one can simply do:
-record(frob, {foo, bar="bar", baz}).
to_rec(?RECSPEC(frob), [{baz, "baz"}, {foo, "foo"}])
which yields
#frob{foo="foo", bar="bar", baz="baz"}
I put this into a little "toolbox" library I am building to collect these little "snippets" that just make life easier when developing Erlang applications: ETBX
If you have the values in the same order as in the record, you can convert directly into the record, you just need to precede the name of the record at the first element of the list and then convert the list into a tuple.
Foorecord = list_to_tuple([my_record]++[Val || {_,Val} <- [{foo, val1},{bar, val2},{baz, val3}] ]).

Resources