-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlistutils.ml
155 lines (127 loc) · 4.24 KB
/
listutils.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
open Function
(* mustn't open Tuple ... *)
(* This file is part of Arsenic, a proofchecker for New Lace logic.
Copyright (c) 2015 Richard Bornat.
Licensed under the MIT license (sic): see LICENCE.txt or
https://opensource.org/licenses/MIT
*)
let string_of_list string_of sepstr xs = String.concat sepstr (List.map string_of xs)
let bracketed_string_of_list string_of xs = "[" ^ string_of_list string_of ";" xs ^ "]"
let bracketed_lines_of_list string_of xs =
"[" ^ string_of_list (fun x -> "\n " ^ string_of x) ";" xs ^ "]"
let string_of_setlist string_of xs = "{" ^ string_of_list string_of ";" xs ^ "}"
let null = function [] -> true | _ -> false
let singleton = function [_] -> true | _ -> false
let cons x xs = x::xs
(* fold_right to keep things in input order. Hang the inefficiency! *)
let (><) xs ys =
List.fold_right
(fun x pairs ->
List.fold_right (fun y pairs -> (x,y)::pairs) ys pairs)
xs
[]
let notself_crossprod xs =
let r = xs><xs in
List.filter (not <.> uncurry2 (==)) r
let numbered xs = Array.to_list (Array.mapi (fun i x -> i,x) (Array.of_list xs))
let rec nodups eq = function
| [] -> true
| x::xs -> not (List.exists (eq x) xs) && nodups eq xs
let last xs = List.nth xs (List.length xs - 1)
let mapfold f x ys =
let rec mtl zs x = function
| [] -> x, List.rev zs
| y::ys -> let x',z = f x y in
mtl (z::zs) x' ys
in
mtl [] x ys
let lookup x xs = try Some(List.assoc x xs) with _ -> None
let mappedby = List.mem_assoc
let (<@>) xys x = List.assoc x xys
let (<@@>) xys x = List.assq x xys
(* don't use this: Maps are easier
let memofun newf =
let table = ref [] in
let lookup x =
try (!table)<@>x
with Not_found ->
(let y = newf x in
table := (x,y)::!table;
y
)
in
lookup
*)
let rec ncombine xss =
let bad () =
let shape =
bracketed_string_of_list (bracketed_string_of_list (fun _ -> ".")) xss
in
raise (Invalid_argument ("Listutils.ncombine " ^ shape))
in
match xss with
| [] -> []
| []::xss' -> if List.exists (not <.> null) xss' then bad()
else xss
| (x::xs)::xss ->
let hds,tails =
List.fold_left (fun (hds,tails) xs -> match xs with
| x::xs -> x::hds, xs::tails
| _ -> bad ()
)
([x],[xs])
xss
in
try List.rev hds::ncombine (List.rev tails)
with Invalid_argument _ -> bad ()
let rec interpconcat interp xs =
match xs with
| [] -> []
| [x] -> x
| x::xs -> List.concat [x;interp;interpconcat interp xs]
let rec first f xs =
match xs with
| [] -> raise Not_found
| x::xs -> try f x with Not_found -> first f xs
(* oh for the Oxford comma ... *)
let phrase_of_list string_of sep1 sep2 =
(let rec ph = function
| [] -> ""
| [x] -> x
| [x1;x2] -> x1 ^ sep2 ^ x2
| x::xs -> x ^ sep1 ^ ph xs
in
ph
)
<.> List.filter (not <.> Stringutils.is_empty)
<.> List.map string_of
let standard_phrase_of_list string_of = phrase_of_list string_of ", " " and "
let ncase_of sz ss sp =
(function
| [] -> sz ()
| [x] -> ss x
| xs -> sp xs
)
let prefixed_phrase_of_list string_of singular plural =
ncase_of (fun () -> "")
(fun s -> singular ^ " " ^ s)
(fun ss -> plural ^ " " ^ standard_phrase_of_list id ss)
<.> List.filter (not <.> Stringutils.is_empty)
<.> List.map string_of
let string_of_assoc fx fy colon semicolon xys =
String.concat semicolon (List.map (fun (x,y) -> fx x ^ colon ^ fy y) xys)
let vmemofun verbose str string_of_key string_of_target newf =
let table = ref [] in
let lookup x =
if verbose then
Printf.printf "\nvmemofun %s %s; assocs [%s]" str (string_of_key x) (string_of_assoc string_of_key string_of_target "->" ";" !table);
try (!table)<@>x
with Not_found ->
(let y = newf x in
table := (x,y)::!table;
if verbose then
Printf.printf " -> %s\nnew assocs [%s]" (string_of_target y) (string_of_assoc string_of_key string_of_target "->" ";" !table);
y
)
in
lookup