Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to get a sub list from a list in ocaml

Tags:

list

ocaml

I'm looking at the List documentation. It seems the library does not provide a sublist function.

I'm trying to get list of elements from i to j. Now I have to write it as:

let rec sublist list i j =
  if i > j then
    []
  else
    (List.nth list i) :: (sublist list (i+1) j)

which is quite concise but I'm questioning the efficiency of List.nth, because if it's O(n), I would rather have to write it in a less concise way.

I'm wondering why didn't they provide List.sublist func, if List.nth is not O(1), because it's such a quite common operation..

like image 200
romerun Avatar asked Apr 25 '10 22:04

romerun


People also ask

How do I split a list into two lists in OCaml?

Just have a function that takes the original list and a empty list. Build up the empty list(with the first half of the original list) until you reach the halfway point and then use the remainder of the original list and the built up empty list to generate your pairs.

How do I truncate a list in OCaml?

Hence, to truncate a list, you need to create a new list that contains only the first elements (this is the only way to get the desired truncated list). let truncate : 'a -> 'a list -> 'a list = fun elt queue -> ...

What does list Fold_left do in OCaml?

So fold_left is "folding in" elements of the list from the left to the right, combining each new element using the operator.


2 Answers

While the answer provided by Pascal implements a nice candidate for List.sublist the right answer is that you should probably better use an array of a list. The Array modules implements the Array.sub function that you might use.

While in many imperatives languages such as C++ or Perl there is essentially no difference between lists and arrays, this is not the same in OCaml where:

  • Lists are better suited for recursive treatments and sequential access, i.e. is usually a better candidate as an array as argument to a recursive function, and you usually want to take a look at all the elements of the list.

  • Arrays are better suited for random access, structure alteration (such as sorting), or for numerical computations.

like image 160
Michaël Le Barbier Avatar answered Oct 11 '22 18:10

Michaël Le Barbier


let rec sublist b e l = 
  match l with
    [] -> failwith "sublist"
  | h :: t -> 
     let tail = if e=0 then [] else sublist (b-1) (e-1) t in
     if b>0 then tail else h :: tail
;;

sublist 3 5 [1;2;3;4;5;6;7;8;9] ;;
- : int list = [4; 5; 6]

The above is more or less a deforested version of newacct's solution. newacct's solution allocates an intermediate list (drop i list), which is possible for the compiler to optimize away in Haskell but much harder in ML. Therefore his version is perfectly fine for a Haskell function and marginally sub-optimal for an ML one. The difference between the two is only a constant factor: both are O(e). zrr's version is O(length(l)) since List.filteri doesn't know that f only returns false after a while, it calls it for all elements in l.

I'm not very happy to let b go negative but the version where it doesn't is more complicated.

One reference among quite a few for deforestation if you're interested: http://homepages.inf.ed.ac.uk/wadler/topics/deforestation.html

like image 43
Pascal Cuoq Avatar answered Oct 11 '22 17:10

Pascal Cuoq