Tail call optimization with a function returning a tuple - ocaml

I have a simple function that splits a list at an index:
let rec split_at ls i =
match i with
| 0 -> ([], ls)
| _ ->
match ls with
| [] -> raise Not_found
| h::t ->
match split_at t (i - 1) with
| (left, right) -> ((h :: left), right)
Is there a way to get the OCaml compiler to optimize this function to use constant stack space?
I have tried using #tail_mod_cons but it doesn't work. I understand that the call is not really in tail position, but it feels like it should be optimizable.

Firstly, let's clean up your function by pattern matching on a tuple of i and ls and using a local let binding rather than that last match expression.
let rec split_at ls i =
match i, ls with
| 0, _ -> ([], ls)
| _, [] -> raise Not_found
| _, h::t ->
let (left, right) = split_at t (i - 1) in
(h::left, right)
As Jeffrey says, the cons (::) is not in tail call position, so tail_mod_cons does nothing for you. If we try to use it, we'll get a warning to that effect:
Lines 1-7, characters 33-20:
Warning 71 [unused-tmc-attribute]: This function is marked #tail_mod_cons
but is never applied in TMC position.
As also hinted, though, it's trivial to let your brain modify this for tail-recursion using an accumulator.
let split_at lst n =
let rec aux lst n first_part =
match n, lst with
| 0, _ -> (List.rev first_part, lst)
| _, [] -> raise Not_found
| _, h::t -> aux t (n - 1) (h::first_part)
in
aux lst n []

The function split_at can be written in a partial tail_mod_cons way if we split the construction of the new prefix from the part of the function returning the suffix using a reference:
let[#tail_mod_cons] rec split_at r ls i =
match i with
| 0 -> r := ls; []
| _ ->
match ls with
| [] -> raise Not_found
| h::t ->
h:: (split_at[#tailcall]) r t (i - 1)
let split_at ls i =
let r = ref [] in
let l = split_at r ls i in
l, !r

The way I understand it, "tail mod cons" works by passing an incomplete constructor into which the called function should place its answer. So to make the optimization work you have to be able to put your problem into a form for which this is a solution.
Maybe it would work if you split the problem into two parts. The first part duplicates the first n elements of the list. The second part returns all but the first n elements of the list.
The second part is trivial to implement tail recursively. And it seems like you should be able to duplicate a list using "tail mod cons".

Related

F# match pattern discriminator not defined issue

im in the process of writing a transposing recursive function and i have stopped at a problem. So i want to have a check using match by calling isTable function to verify that the input M is a valid table, however it errors and im not sure how to fix it
let isTable list =
match List.map List.length list |> List.distinct |> List.length with
| 1 -> true
| _ -> false
let rec transpose M =
match M with
| []::_ -> []
| (isTable M) -> [] // i want to check here if M is a valid table
| _ -> (List.map List.head M::transpose(List.map List.tail M))
error FS0039: The pattern discriminator 'isTable' is not defined.
Active patterns are one approach, but the overhead of adding one just for a single use is not worth it. An easy and uncluttered solution would be to use a when clause:
let rec transpose M =
match M with
| []::_ -> []
| _ when isTable M -> []
| _ -> (List.map List.head M::transpose(List.map List.tail M))
None of the answers yet show how to turn your case into an Active Pattern. This is particularly useful for (1) readability and (2) reusability of code. Assuming you'd need isTable more than once, this can be beneficial.
/// Active pattern, must start with capital letter.
let (|IsTable|_|) list =
match List.map List.length list |> List.distinct with
| [_] -> Some list
| _ -> None
let rec transpose M =
match M with
| []::_ -> []
| IsTable M -> [] // using the active pattern
| _ ->
List.map List.head M::transpose(List.map List.tail M)
As an aside, your isTable function matched over List.length result. A List.length iterates over the whole list and is O(n). Since we're only interested if the result is one item, the above approach will be more efficient, removing at least one iteration from the code.
Try something like
let rec transpose M =
match M with
| []::_ -> []
| _ -> match (isTable M) with
| true - > [] // i want to check here if M is a valid table
| _ -> (List.map List.head M::transpose(List.map List.tail M))
As a matter of programming style I'd recommend adding a data constructor like Table so that you can match on it but this should get things working.

OCaml function to check if list is palindrome with floor(n/2) recursive calls and no list allocation

I have this task on uni, I have researched for a long time, but I cannot find out, how to write this function.
I need it to check if a list is a palindrome, call itself recursively at most floor(n/2) times and not allocate any auxiliary list (so I can use no list constructors).
Any ideas? Tbh, I would like an algorithm than a full solution.
I have come up with this and it works:
let palindrom l =
let rec aux l0 l1 =
match (l0, l1) with
| _,[] -> (true,[])
| hd :: tl, [x] -> (hd = x, tl)
| _, hd1 :: tl1 -> let (pal, ll) = aux l0 tl1 in
match ll with
| [] -> (pal, [])
| hd::tl -> (pal && hd1 = hd, tl) in
match l with
[] -> true
| _ -> fst (aux l l)
You can use a recursive helper function that
on the way in, takes two arguments: a remainder of the list, and a remainder of the list that is twice as far away from the start of the list to be checked.
reaches its base case in the middle of the list to be checked (when the second list becomes empty, or - in the case of an odd length - has a single element only)
on the way out, returns an option for a list, the remainder that still has to be checked in reverse for equality - or None when the palindrome failed to match
Example:
// in
hannah hannah
annah nnah
nnah ah
nah
// out
n <-> nah
a <-> ah
h <-> h

What is wrong with this OCAML function?

Here is my original code.
let rec reverse l =
match l with
| [] -> []
| (h::t) -> (reverse t) :: h
The cons :: operator takes an element as left-hand argument and a list as right-hand argument. Here, you do the opposite which does not work.
The right way to add an element at the element at the end of a list is to use list concatenation:
let rec reverse l =
match l with
| [] -> []
| h :: t -> (reverse t) # [h]
That code is not optimal though, and you may want to make it tail recursive.

Ocaml Pattern matching not doing as I expect

I'm having a little trouble with my OCaml program:
let moveRight ls i =
match getn ls (i+1) with
|O -> replacex (replacex ls i O) (i+1) R
|_ -> replacex (replacex ls i O) (i+2) R;
Replacex works, and replaces the i'th element in list ls with x.
But my program above doesn't.
It is supposed to do the following:
If a list is [R; L; O], and i = 1, it should change it to [O;L;R], but it doesn't. It seems to create the original list inside the new list and does this: [R; R; O; O; L; O].
Help would be appreciated, I'm not sure where I'm going wrong!
Thanks
EDIT:
replacex is as follows:
let replacex ls i x = firstx ls (i-1) # [x] # lastx ls ((length ls)-i);;
And it's dependant functions are:
let rec firstx ls i =
match ls with
| [] -> []
| x::xs -> if i <> 1 then x::firstx xs (i-1) else [x];;
let rec reverse ls =
match ls with
|[] -> []
| x::xs -> reverse xs # [x];;
let lastx ls i = reverse (firstx (reverse ls) i);;
let rec length ls =
match ls with
| [] -> 0
| x::xs -> 1+length xs;;
let rec getn ls i = match ls with
| [] -> raise (Failure "empty list")
| first::rest ->
if i = 0 then first
else getn rest (i-1);;
In fact, replacex function doesn't work correctly if you're trying to replace second element of the list. This leads to the call to firstx with second argument equal to 0. And your implementation of firstx returns a full list in that case. You should either fix indices in, or rethink what is first zero elements.

Find unique elements in a list in OCaml

I am working on a project with OCaml and there are some problems regarding to arrays that I am not sure with. I am not allowed to use the List module, so please give me some idea or suggestion with my works.
First, I already implemented a function 'a list -> 'a list called uniq that return a list of the uniq elements in an array, for example uniq [5;6;5;4] => [6;5;4]
Here is my implementation:
let rec uniq x =
let rec uniq_help l n =
match l with
[] -> []
| h :: t -> uniq_help t, n if (n = h) else (h :: (uniq_help(t, n)))
match x with
[] -> []
| h::t -> uniq_help t, h
;;
I mot sure this is a correct implementation, can someone give me some suggestion or correctness?
You functions are syntactically incorrect for various reasons:
uniq_help takes two elements so you have to invoke it using uniq_help t n, not uniq_help(t, n) and the like.
an if/else expression should have the form of if cond then expr1 else expr2.
to use uniq_help locally in uniq, you need an in keyword.
After fixing syntax errors, your function looks like:
let rec uniq x =
let rec uniq_help l n =
match l with
| [] -> []
| h :: t -> if n = h then uniq_help t n else h::(uniq_help t n) in
match x with
| [] -> []
| h::t -> uniq_help t h
However, to be sure that each element is unique in the list, you have to check uniqueness for all of its elements. One quick fix could be:
let rec uniq x =
(* uniq_help is the same as above *)
match x with
| [] -> []
| h::t -> h::(uniq_help (uniq t) h)