Deleting Elements From a List by Indexes in OCaml Example
Implement an OCaml function which, given a list l : 'a list
of items and a list r : int list
of indices i
such that 0 <= i && i < length l
, computes the result of deleting from l
those values with indices in r
. The list r
is sorted in ascending order of value and does not contain duplicates.
Solution
To solve this problem, we proceed by recursively traversing the structure of both input lists l
and r
. We also need to keep track of the index i
of the element in l
we're currently visiting. This is accomplished with the delete_aux
helper function.
In the case where r = []
, we have exhausted the indices list of elements to delete from l
, so we simply return l
. If both lists l
and r
are non-empty, then we need to check whether the value of the topmost element d
of r
is the index of the topmost element x
of l
.
let delete : 'a list -> int list -> 'a list =
let rec delete_aux : int -> 'a list -> int list -> 'a list =
fun i l r ->
match (l, r) with
| l, [] -> l
| x :: xs, d :: ds ->
if i > d then
raise (Failure "delete")
else if i = d then
delete_aux (i + 1) xs ds
else
x :: delete_aux (i + 1) xs r
| _ -> raise (Failure "delete")
in
fun l r -> delete_aux 0 l r
The recursive call to delete_aux
in x :: delete_aux (i + 1) xs r
is not a tail call. We can fix this using continuation-passing style:
let delete : 'a list -> int list -> 'a list =
let rec delete_aux : int -> 'a list -> int list -> ('a list -> 'b) -> 'b =
fun i l r return ->
match (l, r) with
| l, [] -> return l
| x :: xs, d :: ds ->
if i > d then
raise (Failure "delete")
else if i = d then
delete_aux (i + 1) xs ds return
else
delete_aux (i + 1) xs r (fun l' -> return (x :: l'))
| _ -> raise (Failure "delete")
in
fun l r -> delete_aux 0 l r (fun l' -> l')