ocaml/stdlib/list.ml

222 lines
5.3 KiB
OCaml

(***********************************************************************)
(* *)
(* 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, with *)
(* the special exception on linking described in file ../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-1000) 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;;