How to use erlang fun recursive function? - recursion

I am trying to decode frames with variable length and options (such as the TLV in ethernet frames)
In order to do that, I was thinking about doing a fun recursive function :
fun (Fields, Bin) ->
Parse =
fun (P, F, <<Length, Rest/binary>>) ->
P(P, F#{first => Length}, Rest)
end,
Parse(Parse, Fields, Bin)
end.
So Bin is the input frame for example : 40 02 12 45 01 50
So first byte is the type of frame, 02 is the length of following data 12 45, 01 is the length is the following data 50 and so on.
But my function doesn't work as expected using the funny trick
I am returning JSON object because it's send over MQTT.

What you're doing there really is only reading out the length, and don't do much with the Rest. You'd need to first declare an exit condition, i.e. when the TLV is empty -> just return the accummulator; And use the pattern match to read out the values based on the Length:
parse(<<>>, Acc) -> Acc; %% finished with the list
parse(<<Length, Rest/binary>>, Acc) ->
<<Value:Length/binary, Carry/binary>> = Rest.
%% Value for the tag, Carry to be passed back on the recursion.
%% Assuming that `Acc` is a list of Values.
parse(Carry, Acc ++ [Value]).
You can use the above to read out the values, and can do something similar for getting the type first as:
tlv(<<Type, Values/binary>>) ->
%% Return at tuple with the Type and the values.
{Type, parse(Values, [])}.

You could write the function like this:
fun(<<Type, Packet/binary>>) ->
{Type,
fun Parse(<<>>) ->
[];
Parse(<<Length, Data:Length/bytes, Rest/binary>>) ->
[Data] ++ Parse(Rest)
end(Packet)}
end.
This returns {40,[<<12,45>>,<<50>>]} for your sample data.
The outer fun takes the frame type (40 in this case), and returns it along with the list of the data fields. The inner fun takes one length byte and the corresponding number of data bytes, and returns the data and makes a recursive call to itself - until it reaches the end of the binary.
The inner fun is a "named fun": it calls itself Parse, and is therefore able to call itself without needing to pass itself as an argument. The name Parse is not visible outside the fun. See this question for details and examples.

Related

Empty tuple in sml

I am writing a function that's supposed to return a list of 'a * 'a tuples .I actually use it only for integers though. The thing is , when I am writing the base case in my pattern matching I don't know how to make it compile: I tried things like
fun myf [] = []
fun myf [] = [()]
fun myf [] = [(NONE, NONE)]
None, of the 3 above did the work .
I found nothing by searching the web.
The closest you get to "an empty tuple" is the unit value: (). But a list of unit values will only be able to have different lengths, not different values in each element. If you want either an empty value, or some specific value, you can use the 'a option type, e.g.:
fun maximum [] = NONE
| maximum [x] = SOME x
| maximum (x::y::xs) = let val z = Int.max (x, y) in maximum (z::xs) end
If you want a list of 'a option values, you may want to consider why you care about gathering multiple NONE values in different positions. There are use-cases for this, but often you may be happy without them, too.

Naming a function that applies a list of functions to one value

But how do you call a function that takes a [X -> Y] and a X and gives back a [Y]? I.e. a function that takes a list of functions and a value and gives back a list of results when all functions from the list are applied to the given argument.
Most of the common simple higher order functions have consisent simple names in most programming languages:
If a function takes [X] and f: X -> Y and gives back a [Y}, then it's commonly called map. (Sometimes it's a method, sometimes a function, but the principle is always the same)
If a function takes a [X] and a f: X -> boolean and gives back a [X] it's called filter.
If a function takes a [X] and a f: X -> [Y] and gives backa [Y], it's called flatMap.
Note that it is of course trivial to implement this in any language that has support for functional programming and that's not my question. My question is about naming. I haven't found any language that has this built in, so I couldn't copy the name from anywhere. But it feels like this is such a basic thing that there should be a globally understood name.
Functions have type too. A function of type a -> b has a different type than a function of type a -> c.
So, you have a function x -> y. For conceptual sake, we'll call that type z. And you have a list of these z-type functions, but you want a list of y, so you need [z] -> [y] – which is exactly what map does.
If we expand z back to our original type, x -> y, we can see the final type of the function we're trying to make: [x -> y] -> [y]. All that's left is getting from x -> y to y. Let's see apply –
// apply : a -> (a -> b) -> b
const apply = x => f =>
f (x)
If we give apply an argument, it gives us back a function of the exact type you're looking for –
apply (2) // : (Number -> b) -> b
apply ("hello") // : (String -> b) -> b
Combining map and apply we achieve our result –
// apply : a -> (a -> b) -> b
const apply = x => f =>
f (x)
// mult : Number -> Number -> Number
const mult = x => y =>
x * y
// listOfFuncs : [ Number -> Number ]
const listOfFuncs =
[ mult (1) // : Number -> Number
, mult (2) // : Number -> Number
, mult (3) // : Number -> Number
, mult (4) // : Number -> Number
]
console .log
( listOfFuncs .map (apply (2)) // [ 2, 4, 6, 8 ] : [ Number ]
, listOfFuncs .map (apply (10)) // [ 10, 20, 30, 40 ] : [ Number ]
)
I've never seen a unique name given to this particular combination of functions, but I don't think it needs one either. map and apply are both simple and I think they encode your intention directly.
Another way to approach this might be to deconstruct your question first. "Naming a function that applies a list of functions to one value" is an over-stated need if you already have a function that takes a list of one type and produces a list of a new type (map). The unique need here is the ability to apply a constant to a function, which we saw was easily shown with apply.
Combining effects of simple programs is what makes functional programming powerful. Writing a program that does too many things make it less reusable. Struggling to name a function can be an indicator that you're making a misstep.

SMLNJ powerset function

I am trying to print the size of a list created from below power set function
fun add x ys = x :: ys;
fun powerset ([]) = [[]]
| powerset (x::xr) = powerset xr # map (add x) (powerset xr) ;
val it = [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]] : int list list;
I have the list size function
fun size xs = (foldr op+ 0 o map (fn x => 1)) xs;
I couldnt able to merge these two functions and get the result like
I need something like this:
[(0,[]),(1,[3]),(1,[2]),(2,[2,3]),(1,[1]),(2,[1,3]),(2,[1,2]),(3,[1,2,3])]
Could anyone please help me with this?
You can get the length of a list using the built-in List.length.
You seem to forget to mention that you have the constraint that you can only use higher-order functions. (I am guessing you have this constraint because others these days are asking how to write powerset functions with this constraint, and using foldr to count, like you do, seems a little constructed.)
Your example indicates that you are trying to count each list in a list of lists, and not just the length of one list. For that you'd want to map the counting function across your list of lists. But that'd just give you a list of lengths, and your desired output seems to be a list of tuples containing both the length and the actual list.
Here are some hints:
You might as well use foldl rather than foldr since addition is associative.
You don't need to first map (fn x => 1) - this adds an unnecessary iteration of the list. You're probably doing this because folding seems complicated and you only just managed to write foldr op+ 0. This is symptomatic of not having understood the first argument of fold.
Try, instead of op+, to write the fold expression using an anonymous function:
fun size L = foldl (fn (x, acc) => ...) 0 L
Compare this to op+ which, if written like an anonymous function, would look like:
fn (x, y) => x + y
Folding with op+ carries some very implicit uses of the + operator: You want to discard one operand (since not its value but its presence counts) and use the other one as an accumulating variable (which is better understood by calling it acc rather than y).
If you're unsure what I mean about accumulating variable, consider this recursive version of size:
fun size L =
let fun sizeHelper ([], acc) = acc
| sizeHelper (x::xs, acc) = sizeHelper (xs, 1+acc)
in sizeHelper (L, 0) end
Its helper function has an extra argument for carrying a result through recursive calls. This makes the function tail-recursive, and folding is one generalisation of this technique; the second argument to fold's helper function (given as an argument) is the accumulating variable. (The first argument to fold's helper function is a single argument rather than a list, unlike the explicitly recursive version of size above.)
Given your size function (aka List.length), you're only a third of the way, since
size [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]]
gives you 8 and not [(0,[]),(1,[3]),(1,[2]),(2,[2,3]),...)]
So you need to write another function that (a) applies size to each element, which would give you [0,1,1,2,...], and (b) somehow combine that with the input list [[],[3],[2],[2,3],...]. You could do that either in two steps using zip/map, or in one step using only foldr.
Try and write a foldr expression that does nothing to an input list L:
foldr (fn (x, acc) => ...) [] L
(Like with op+, doing op:: instead of writing an anonymous function would be cheating.)
Then think of each x as a list.

Memoisation in OCaml and a Reference List

I am learning OCaml. I know that OCaml provides us with both imperative style of programming and functional programming.
I came across this code as part of my course to compute the n'th Fibonacci number in OCaml
let memoise f =
let table = ref []
in
let rec find tab n =
match tab with
| [] ->
let v = (f n)
in
table := (n, v) :: !table;
v
| (n', v) :: t ->
if n' = n then v else (find t n)
in
fun n -> find !table n
let fibonacci2 = memoise fibonacci1
Where the function fibonacci1 is implemented in the standard way as follows:
let rec fibonacci1 n =
match n with
| 0 | 1 -> 1
| _ -> (fibonacci1 (n - 1)) + (fibonacci1 (n - 2))
Now my question is that how are we achieving memoisation in fibonacci2. table has been defined inside the function fibonacci2 and thus, my logic dictates that after the function finishes computation, the list table should get lost and after each call the table will get built again and again.
I ran some a simple test where I called the function fibonacci 35 twice in the OCaml REPL and the second function call returned the answer significantly faster than the first call to the function (contrary to my expectations).
I though that this might be possible if declaring a variable using ref gives it a global scope by default.
So I tried this
let f y = let x = ref 5 in y;;
print_int !x;;
But this gave me an error saying that the value of x is unbounded.
Why does this behave this way?
The function memoise returns a value, call it f. (f happens to be a function). Part of that value is the table. Every time you call memoise you're going to get a different value (with a different table).
In the example, the returned value f is given the name fibonacci2. So, the thing named fibonacci2 has a table inside it that can be used by the function f.
There is no global scope by default, that would be a huge mess. At any rate, this is a question of lifetime not of scope. Lifetimes in OCaml last as long as an object can be reached somehow. In the case of the table, it can be reached through the returned function, and hence it lasts as long as the function does.
In your second example you are testing the scope (not the lifetime) of x, and indeed the scope of x is restricted to the subexpresssion of its let. (I.e., it is meaningful only in the expression y, where it's not used.) In the original code, all the uses of table are within its let, hence there's no problem.
Although references are a little tricky, the underlying semantics of OCaml come from lambda calculus, and are extremely clean. That's why it's such a delight to code in OCaml (IMHO).

Sublists of N length function in Erlang style

I've been learning Erlang and tried completing some practise functions. I struggled making one function in particular and think it might be due to me not thinking "Erlang" enough.
The function in question takes a list and a sublist size then produces a list of tuples containing the number of elements before the a sublist, the sublist itself and the number of elements after the sublist. For example
sublists(1,[a,b,c])=:=[{0,[a],2}, {1,[b],1}, {2,[c],0}].
sublists(2,[a,b,c])=:=[{0,[a,b],1}, {1,[b,c],0}].
My working solution was
sublists(SubListSize, [H | T]) ->
Length = length(1, T),
sublists(SubListSize, Length, Length-SubListSize, [H|T], []).
sublists(_, _, -1, _, Acc) -> lists:reverse(Acc);
sublists(SubSize, Length, Count, [H|T], Acc) ->
Sub = {Length-SubSize-Count, grab(SubSize, [H|T],[]),Count},
sublists(SubSize, Length, Count-1, T, [Sub|Acc]).
length(N, []) -> N;
length(N, [_|T]) -> length(N+1, T).
grab(0, _, Acc) -> lists:reverse(Acc);
grab(N, [H|T], Acc) -> grab(N-1, T, [H|Acc]).
but it doesn't feel right and I wondered if there was a better way?
There was an extension that asked for the sublists function to be re-implemented using a list comprehension. My failed attempt was
sublist_lc(SubSize, L) ->
Length = length(0, L),
Indexed = lists:zip(L, lists:seq(0, Length-1)),
[{I, X, Length-1-SubSize} || {X,I} <- Indexed, I =< Length-SubSize].
As I understand it, list comprehensions can't see ahead so I was unable to use my grab function from earlier. This again makes me thing there must be a better way of solving this problem.
I show a few approaches below. All protect against the case where the requested sublist length is greater than the list length. All use functions from the standard lists module.
The first one uses lists:split/2 to capture each sublist and the length of the remaining tail list, and uses a counter C to keep track of how many elements precede the sublist. The length of the remaining tail list, named Rest, gives the number of elements that follow each sublist.
sublists(N,L) when N =< length(L) ->
sublists(N,L,[],0).
sublists(N,L,Acc,C) when N == length(L) ->
lists:reverse([{C,L,0}|Acc]);
sublists(N,[_|T]=L,Acc,C) ->
{SL,Rest} = lists:split(N,L),
sublists(N,T,[{C,SL,length(Rest)}|Acc],C+1).
The next one uses two lists of counters, one indicating how many elements precede the sublist and the other indicating how many follow it. The first is easily calculated by simply counting from 0 to the length of the input list minus the length of each sublist, and the second list of counters is just the reverse of the first. These counter lists are also used to control recursion; we stop when each contains only a single element, indicating we've reached the final sublist and can end the recursion. This approach uses the lists:sublist/2 call to obtain all but the final sublist.
sublists(N,L) when N =< length(L) ->
Up = lists:seq(0,length(L)-N),
Down = lists:reverse(Up),
sublists(N,L,[],{Up,Down}).
sublists(_,L,Acc,{[U],[D]}) ->
lists:reverse([{U,L,D}|Acc]);
sublists(N,[_|T]=L,Acc,{[U|UT],[D|DT]}) ->
sublists(N,T,[{U,lists:sublist(L,N),D}|Acc],{UT,DT}).
And finally, here's a solution based on a list comprehension. It's similar to the previous solution in that it uses two lists of counters to control iteration. It also makes use of lists:nthtail/2 and lists:sublist/2 to obtain each sublist, which admittedly isn't very efficient; no doubt it can be improved.
sublists(N,L) when N =< length(L) ->
Up = lists:seq(0,length(L)-N),
Down = lists:reverse(Up),
[{U,lists:sublist(lists:nthtail(U,L),N),D} || {U,D} <- lists:zip(Up,Down)].
Oh, and a word of caution: your code implements a function named length/2, which is somewhat confusing because it has the same name as the standard length/1 function. I recommend avoiding naming your functions the same as such commonly-used standard functions.

Resources