spotlib / lib / xlist.ml

open List

let iter_until f ls = 
  let st = ref `Continue in
  List.iter (fun x -> 
    match f x with
    | `Break b -> st := `Break b; raise Exit
    | `Continue -> ()) ls;
  match !st with
  | `Continue -> None
  | `Break v -> Some v

let iteri f l =
  let rec iter n = function
    | [] -> ()
    | x::xs -> f n x; iter (n+1) xs
  in
  iter 0 l

let mapi f l = 
  let rec map n = function
    | [] -> []
    | x::xs -> f n x :: map (n+1) xs
  in
  map 0 l

let from_to f t =
  let rec from_to st f t =
    if f > t then rev st
    else from_to (f::st) (f+1) t
  in
  from_to [] f t

let init_from_to f t fn =
  let rec loop st i =
    if i > t then rev st
    else loop (fn i :: st) (i+1)
  in
  loop [] f
  
let find_opt f ls = try Some (List.find f ls) with Not_found -> None 

let rec find_map_opt f = function
  | [] -> None
  | x::xs ->
      match f x with
      | Some v -> Some v
      | None -> find_map_opt f xs

(** mapMaybe of Haskell *)
let filter_map f lst =
  List.rev (List.fold_left (fun st x ->
    match f x with
    | Some v -> v :: st
    | None -> st) [] lst)

(** concatMap of Haskell *)
let concat_map f l = List.concat (List.map f l)

let take n xs =
  let rec take_ n st xs =
    if n <= 0 then st
    else match xs with
    | [] -> st
    | x::xs -> take_ (n-1) (x::st) xs
  in
  List.rev (take_ n [] xs)

let split_at n xs =
  let rec split_at_ n st xs =
    if n <= 0 then st, xs
    else match xs with
    | [] -> st, []
    | x::xs -> split_at_ (n-1) (x::st) xs
  in
  let r, dropped = split_at_ n [] xs in
  List.rev r, dropped

let rec drop n xs =
  if n <= 0 then xs
  else match xs with
  | [] -> []
  | _::xs -> drop (n-1) xs

let span p xs =
  let rec span_ st = function
    | [] -> List.rev st, []
    | x::xs when p x -> span_ (x::st) xs
    | l -> List.rev st, l
  in
  span_ [] xs

let unique xs =
  let rec unique st = function
    | [] -> List.rev st
    | x::xs ->
        let st' = if List.mem x st then st else x::st in
        unique st' xs
  in
  unique [] xs

let is_unique key xs =
  let rec is_unique st = function
    | [] -> None
    | x::xs ->
        let k = key x in
        try 
          let x' = List.assoc k st in
          Some (x,x')
        with Not_found -> is_unique ((k,x)::st) xs
  in
  is_unique [] xs

let rec intersperse x = function
  | [] -> []
  | [y] -> [y]
  | y::ys -> y::x::intersperse x ys

let rec last = function
  | [] -> failwith "Xlist.last"
  | [x] -> x
  | _::xs -> last xs

let assoc_all k = 
  let rec aux rev = function
    | [] -> List.rev rev
    | (k',v)::kvs when k = k' -> aux (v::rev) kvs
    | _::kvs -> aux rev kvs
  in
  aux []
  
let scani_left f acc xs =
  let rec scan acc pos xs = match pos, xs with
    | _pos, [] -> acc
    | pos, x::xs ->
        match f pos acc x with
        | `Continue acc -> scan acc (pos+1) xs
        | `Stop acc -> acc
  in
  scan acc 0 xs
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.