61 lines
1.6 KiB
OCaml
61 lines
1.6 KiB
OCaml
let assoc_opt key items =
|
|
let rec search = function
|
|
| [] -> None
|
|
| (candidate, value) :: rest -> if candidate = key then Some value else search rest
|
|
in
|
|
search items
|
|
|
|
let hashtbl_find_opt table key = try Some (Hashtbl.find table key) with Not_found -> None
|
|
|
|
let rec filter_map f = function
|
|
| [] -> []
|
|
| item :: rest -> (
|
|
match f item with
|
|
| Some value -> value :: filter_map f rest
|
|
| None -> filter_map f rest)
|
|
|
|
let rec concat_map f = function
|
|
| [] -> []
|
|
| item :: rest -> f item @ concat_map f rest
|
|
|
|
let rec list_init count f =
|
|
if count <= 0 then []
|
|
else
|
|
let head = f 0 in
|
|
let tail = list_init (count - 1) (fun index -> f (index + 1)) in
|
|
head :: tail
|
|
|
|
let rec take count items =
|
|
if count <= 0 then []
|
|
else
|
|
match items with
|
|
| [] -> []
|
|
| item :: rest -> item :: take (count - 1) rest
|
|
|
|
let rec drop count items =
|
|
if count <= 0 then items
|
|
else match items with [] -> [] | _ :: rest -> drop (count - 1) rest
|
|
|
|
let contains value items = List.exists (fun item -> item = value) items
|
|
|
|
let index_of_char text character =
|
|
let rec search index =
|
|
if index >= String.length text then None
|
|
else if text.[index] = character then Some index
|
|
else search (index + 1)
|
|
in
|
|
search 0
|
|
|
|
let string_before_char text character =
|
|
match index_of_char text character with
|
|
| Some index -> String.sub text 0 index
|
|
| None -> text
|
|
|
|
let starts_with prefix text =
|
|
String.length text >= String.length prefix && String.sub text 0 (String.length prefix) = prefix
|
|
|
|
let rec join separator = function
|
|
| [] -> ""
|
|
| [ single ] -> single
|
|
| item :: rest -> item ^ separator ^ join separator rest
|