(***********************************************************************) (* *) (* Objective Caml *) (* *) (* Xavier Leroy, projet Cristal, INRIA Rocquencourt *) (* *) (* Copyright 1996 Institut National de Recherche en Informatique et *) (* en Automatique. All rights reserved. This file is distributed *) (* under the terms of the GNU Library General Public License. *) (* *) (***********************************************************************) (* $Id$ *) (* List operations *) let rec length_aux len = function [] -> len | a::l -> length_aux (len + 1) l let length l = length_aux 0 l let hd = function [] -> failwith "hd" | a::l -> a let tl = function [] -> failwith "tl" | a::l -> l let rec nth l n = match l with [] -> failwith "nth" | a::l -> if n = 0 then a else if n > 0 then nth l (n-1) else invalid_arg "List.nth" let append = (@) let rec rev_append l1 l2 = match l1 with [] -> l2 | a :: l -> rev_append l (a :: l2) let rev l = rev_append l [] let rec flatten = function [] -> [] | l::r -> l @ flatten r let concat = flatten let rec map f = function [] -> [] | a::l -> let r = f a in r :: map f l let rev_map f l = let rec rmap_f accu = function | [] -> accu | a::l -> rmap_f (f a :: accu) l in rmap_f [] l ;; let rec iter f = function [] -> () | a::l -> f a; iter f l let rec fold_left f accu l = match l with [] -> accu | a::l -> fold_left f (f accu a) l let rec fold_right f l accu = match l with [] -> accu | a::l -> f a (fold_right f l accu) let rec map2 f l1 l2 = match (l1, l2) with ([], []) -> [] | (a1::l1, a2::l2) -> let r = f a1 a2 in r :: map2 f l1 l2 | (_, _) -> invalid_arg "List.map2" let rev_map2 f l1 l2 = let rec rmap2_f accu l1 l2 = match (l1, l2) with | ([], []) -> accu | (a1::l1, a2::l2) -> rmap2_f (f a1 a2 :: accu) l1 l2 | (_, _) -> invalid_arg "List.rev_map2" in rmap2_f [] l1 l2 ;; let rec iter2 f l1 l2 = match (l1, l2) with ([], []) -> () | (a1::l1, a2::l2) -> f a1 a2; iter2 f l1 l2 | (_, _) -> invalid_arg "List.iter2" let rec fold_left2 f accu l1 l2 = match (l1, l2) with ([], []) -> accu | (a1::l1, a2::l2) -> fold_left2 f (f accu a1 a2) l1 l2 | (_, _) -> invalid_arg "List.fold_left2" let rec fold_right2 f l1 l2 accu = match (l1, l2) with ([], []) -> accu | (a1::l1, a2::l2) -> f a1 a2 (fold_right2 f l1 l2 accu) | (_, _) -> invalid_arg "List.fold_right2" let rec for_all p = function [] -> true | a::l -> p a && for_all p l let rec exists p = function [] -> false | a::l -> p a || exists p l let rec for_all2 p l1 l2 = match (l1, l2) with ([], []) -> true | (a1::l1, a2::l2) -> p a1 a2 && for_all2 p l1 l2 | (_, _) -> invalid_arg "List.for_all2" let rec exists2 p l1 l2 = match (l1, l2) with ([], []) -> false | (a1::l1, a2::l2) -> p a1 a2 || exists2 p l1 l2 | (_, _) -> invalid_arg "List.exists2" let rec mem x = function [] -> false | a::l -> a = x || mem x l let rec memq x = function [] -> false | a::l -> a == x || memq x l let rec assoc x = function [] -> raise Not_found | (a,b)::l -> if a = x then b else assoc x l let rec assq x = function [] -> raise Not_found | (a,b)::l -> if a == x then b else assq x l let rec mem_assoc x = function | [] -> false | (a, b) :: l -> a = x || mem_assoc x l let rec mem_assq x = function | [] -> false | (a, b) :: l -> a == x || mem_assq x l let rec remove_assoc x = function | [] -> [] | (a, b as pair) :: l -> if a = x then l else pair :: remove_assoc x l let rec remove_assq x = function | [] -> [] | (a, b as pair) :: l -> if a == x then l else pair :: remove_assq x l let rec find p = function | [] -> raise Not_found | x :: l -> if p x then x else find p l let find_all p = let rec find accu = function | [] -> rev accu | x :: l -> if p x then find (x :: accu) l else find accu l in find [] let filter = find_all let partition p l = let rec part yes no = function | [] -> (rev yes, rev no) | x :: l -> if p x then part (x :: yes) no l else part yes (x :: no) l in part [] [] l let rec split = function [] -> ([], []) | (x,y)::l -> let (rx, ry) = split l in (x::rx, y::ry) let rec combine l1 l2 = match (l1, l2) with ([], []) -> [] | (a1::l1, a2::l2) -> (a1, a2) :: combine l1 l2 | (_, _) -> invalid_arg "List.combine" (** sorting *) external obj_truncate : 'a array -> int -> unit = "obj_truncate" let array_to_list_in_place a = let l = Array.length a in let rec loop accu n p = if p <= 0 then accu else begin if p = n then begin obj_truncate a p; loop (a.(p-1) :: accu) (n-1000) (p-1) end else begin loop (a.(p-1) :: accu) n (p-1) end end in loop [] l l ;; let stable_sort cmp l = let a = Array.of_list l in Array.stable_sort cmp a; array_to_list_in_place a ;; let sort = stable_sort;;