tags:

views:

170

answers:

3

Hi, I'm looking at the List document. 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..

+1  A: 

This is a bit harder than it should be with OCaml's standard library --- the standard library is a bit sparse. If you use one of the extended standard libraries, it gets easier. With Core, for example, you could write:

let sublist list low high =
   List.filteri l ~f:(fun i _ -> i >= low && pos < high)

I imagine something similar is possible with extlib/batteries.

zrr
+3  A: 

Try writing the take (first n items) and drop (everything but the first n items) functions (like in Haskell) first. Then sublist i j lst is just take (j-i) (drop i lst)

newacct
Use an extension library like Batteries Included or Extlib and it'll provide take and drop for you.
Michael E
+4  A: 
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

Pascal Cuoq
Actually, I was wrong: the un-optimized call-by-value evaluation of newacct's function is O(length(l)) too, because of the intermediate list. To preserve the asymptotic complexity O(e) in ML, you would have to `take` first, then `drop`.
Pascal Cuoq