Skip to content

Commit 7ccebcc

Browse files
committed
Add try_pop; Update docs
1 parent 82b95ea commit 7ccebcc

File tree

3 files changed

+87
-66
lines changed

3 files changed

+87
-66
lines changed

src/vec.ml

+18-16
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ let[@inline] make_unsafe capacity length = { data = array_uninit capacity; lengt
1111

1212
let[@inline] make ?capacity:(c=0) () =
1313
if c < 0 then
14-
raise (Invalid_argument "capacity < 0")
14+
raise (Invalid_argument "Negative capacity")
1515
else
1616
make_unsafe c 0
1717

@@ -23,8 +23,8 @@ let[@inline] length v = v.length
2323
let[@inline] capacity v = Array.length v.data
2424

2525
let[@inline] clear v =
26-
v.length <- 0;
27-
v.data <- [||]
26+
v.data <- [||];
27+
v.length <- 0
2828

2929
let[@inline] get v i =
3030
if i < 0 || i >= v.length then
@@ -73,7 +73,7 @@ let[@inline] push a v =
7373
v.length <- new_length;
7474
v.data.(old_length) <- a
7575

76-
let[@inline] pop v =
76+
let[@inline] try_pop v =
7777
if v.length = 0 then
7878
None
7979
else
@@ -83,6 +83,11 @@ let[@inline] pop v =
8383
v.length <- last;
8484
Some a
8585

86+
let[@inline] pop v =
87+
match try_pop v with
88+
| None -> raise (Invalid_argument "Empty vector")
89+
| Some a -> a
90+
8691
let[@inline] singleton a =
8792
{ data = [|a|]
8893
; length = 1
@@ -93,9 +98,9 @@ let try_find f v =
9398
if i = v.length then
9499
None
95100
else
96-
let e = v.data.(i) in
97-
if f e then
98-
Some e
101+
let a = v.data.(i) in
102+
if f a then
103+
Some a
99104
else
100105
go (i + 1)
101106
in
@@ -253,19 +258,16 @@ let filteri f v =
253258
v2
254259

255260
let filter_in_place f v =
256-
let old_l = v.length in
261+
let old_length = v.length in
257262
let l = ref 0 in
258263

259-
for i = 0 to old_l - 1 do
260-
let e = v.data.(i) in
261-
if f e then
262-
(v.data.(!l) <- e; incr l)
263-
done;
264-
265-
for i = !l to old_l - 1 do
266-
v.data.(i) <- Obj.magic 0
264+
for i = 0 to old_length - 1 do
265+
let a = v.data.(i) in
266+
if f a then
267+
(v.data.(!l) <- a; incr l)
267268
done;
268269

270+
Array.fill v.data !l (old_length - !l) (Obj.magic 0);
269271
v.length <- !l
270272

271273
let[@inline] of_array_unsafe a =

src/vec.mli

+28-24
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22

33
type ('a, -'p) t
44

5-
(** [('a, 'p) Vec.t] is a vector of values of type ['a], with mutability permissions ['p].
5+
(** A value of type [('a, 'p) Vec.t] is a vector of values of type ['a], with mutability permissions ['p].
66
7-
['p] is [[`R | `W]] for read-write vectors, [[`R]] for read-only vectors, or [[`W]] for write-only vectors. *)
7+
The permissions can be [[`R | `W]] for read-write vectors, [[`R]] for read-only vectors, or [[`W]] for write-only vectors. *)
8+
9+
(** {1 Reading vector properties} *)
10+
11+
val length: ('a, [>]) t -> int
12+
(** Returns the length of the vector. *)
13+
14+
val capacity: ('a, [>]) t -> int
15+
(** Returns the capacity of the vector. *)
816

917
(** {1 Creating vectors} *)
1018

@@ -28,30 +36,19 @@ val as_read_only: ('a, [> `R]) t -> ('a, [`R]) t
2836
val as_write_only: ('a, [> `W]) t -> ('a, [`W]) t
2937
(** Reinterprets the vector as a write-only vector. *)
3038

31-
(** {1 Basic properties} *)
32-
33-
val length: ('a, [>]) t -> int
34-
(** Returns the length of the vector. *)
35-
36-
val capacity: ('a, [>]) t -> int
37-
(** Returns the capacity of the vector. *)
38-
39-
val reserve: int -> ('a, [> `W]) t -> unit
40-
(** Ensures the vector's capacity is at least as large as the specified value, allocating if necessary. *)
41-
4239
(** {1 Accessing elements} *)
4340

4441
val get: ('a, [> `R]) t -> int -> 'a
4542
(** Gets the value in the vector at the specified index.
4643
@raise [Invalid_argument] if the index is out of bounds. *)
4744

45+
val try_get: ('a, [> `R]) t -> int -> 'a option
46+
(** Gets the value in the vector at the specified index. Returns [None] if the index is out of range. *)
47+
4848
val set: ('a, [> `W]) t -> int -> 'a -> unit
4949
(** Sets the value in the vector at the specified index to the specified value.
5050
@raise [Invalid_argument] if the index is out of bounds. *)
5151

52-
val try_get: ('a, [> `R]) t -> int -> 'a option
53-
(** Gets the value in the vector at the specified index. Returns [None] if the index is out of range. *)
54-
5552
val try_set: ('a, [> `W]) t -> int -> 'a -> bool
5653
(** Sets the value in the vector at the specified index to the specified value. Returns [false] if the index is out of range. *)
5754

@@ -90,26 +87,33 @@ val pretty_print: ('a -> string) -> ('a, [> `R]) t -> string
9087
val clear: ('a, [> `W]) t -> unit
9188
(** Resets the vector to an empty state. *)
9289

90+
val reserve: int -> ('a, [> `W]) t -> unit
91+
(** Ensures the vector's capacity is at least as large as the specified value, allocating if necessary. *)
92+
9393
val shrink_to_fit: ('a, [> `W]) t -> unit
9494
(** Shrinks the vector's internal buffer to only be as large as the vector's length. *)
9595

9696
val push: 'a -> ('a, [> `W]) t -> unit
9797
(** Pushes the specified item onto the end of the vector. *)
9898

99-
val pop: ('a, [`R | `W]) t -> 'a option
100-
(** Pops off the item from the end of the vector. *)
99+
val pop: ('a, [`R | `W]) t -> 'a
100+
(** Pops off the item from the end of the vector.
101+
@raise [Invalid_argument] if the vector is empty. *)
102+
103+
val try_pop: ('a, [`R | `W]) t -> 'a option
104+
(** Pops off the item from the end of the vector. Returns [None] if the vector is empty. *)
101105

102106
val insert_at: int -> 'a -> ('a, [> `W]) t -> unit
103107
(** Inserts an item into the vector at the specified index.
104108
@raise [Invalid_argument] if the index is out of bounds. *)
105109

110+
val try_insert_at: int -> 'a -> ('a, [> `W]) t -> bool
111+
(** Inserts an item into the vector at the specified index. Returns [false] if the index is out of range. *)
112+
106113
val remove_at: int -> ('a, [`R | `W]) t -> 'a
107114
(** Removes and returns the item at the specified index.
108115
@raise [Invalid_argument] if the index is out of bounds. *)
109116

110-
val try_insert_at: int -> 'a -> ('a, [> `W]) t -> bool
111-
(** Inserts an item into the vector at the specified index. Returns [false] if the index is out of range. *)
112-
113117
val try_remove_at: int -> ('a, [`R | `W]) t -> 'a option
114118
(** Removes and returns the item at the specified index. Returns [None] if the index is out of range. *)
115119

@@ -226,12 +230,12 @@ module Infix: sig
226230
val (.![]): ('a, [> `R]) t -> int -> 'a
227231
(** Infix version of {!get}. *)
228232

229-
val (.![]<-): ('a, [> `W]) t -> int -> 'a -> unit
230-
(** Infix version of {!set}. *)
231-
232233
val (.?[]): ('a, [> `R]) t -> int -> 'a option
233234
(** Infix version of {!try_get}. *)
234235

236+
val (.![]<-): ('a, [> `W]) t -> int -> 'a -> unit
237+
(** Infix version of {!set}. *)
238+
235239
val (.?[]<-): ('a, [> `W]) t -> int -> 'a -> bool
236240
(** Infix version of {!try_set}. *)
237241

test/test.ml

+41-26
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ let make _ =
88

99
let v = Vec.make ~capacity:8 () in
1010
assert_equal 0 (Vec.length v);
11-
assert_equal 8 (Vec.capacity v)
11+
assert_equal 8 (Vec.capacity v);
12+
13+
assert_raises ~msg:"make negative capacity" (Invalid_argument "Negative capacity") (Vec.make ~capacity:(-1))
1214

1315
let capacity _ =
1416
let v = Vec.make () in
@@ -31,7 +33,7 @@ let get_set _ =
3133
assert_raises ~msg:"set out of range" (Invalid_argument "Index out of range") (fun () -> v.![0] <- 0);
3234

3335
assert_equal None v.?[0];
34-
assert_bool "try_set out of range" (not @@ v.?[0] <- 0);
36+
assert_bool "try_set out of range" (not (v.?[0] <- 0));
3537

3638
Vec.push 1 v;
3739

@@ -41,6 +43,14 @@ let get_set _ =
4143
assert_bool "try_set in range" (v.?[0] <- 3);
4244
assert_equal (Some 3) v.?[0]
4345

46+
let range _ =
47+
assert_equal [1; 2; 3; 4; 5] (Vec.to_list (1 -- 5));
48+
assert_equal [5; 4; 3; 2; 1] (Vec.to_list (5 -- 1));
49+
50+
assert_equal [1] (Vec.to_list (1 -- 1));
51+
assert_equal [0; 1] (Vec.to_list (0 -- 1));
52+
assert_equal [1; 0] (Vec.to_list (1 -- 0))
53+
4454
let find _ =
4555
let v = 1 -- 5 in
4656

@@ -82,9 +92,11 @@ let push_pop _ =
8292
Vec.push 3 v;
8393
assert_equal 2 (Vec.length v);
8494

85-
assert_equal (Some 3) (Vec.pop v);
86-
assert_equal (Some 1) (Vec.pop v);
87-
assert_equal None (Vec.pop v)
95+
assert_equal (Some 3) (Vec.try_pop v);
96+
assert_equal (Some 1) (Vec.try_pop v);
97+
98+
assert_equal None (Vec.try_pop v);
99+
assert_raises ~msg:"pop empty" (Invalid_argument "Empty vector") (fun () -> Vec.pop v)
88100

89101
let map _ =
90102
let v = 0 -- 4 in
@@ -115,26 +127,28 @@ let cartesian_product _ =
115127
let b = Vec.of_list [10; 20; 30] in
116128
let expected = [1, 10; 1, 20; 1, 30; 2, 10; 2, 20; 2, 30; 3, 10; 3, 20; 3, 30] in
117129

118-
assert_equal expected (Vec.to_list @@ Vec.cartesian_product a b)
130+
assert_equal expected (Vec.to_list (Vec.cartesian_product a b))
119131

120132
let monad_ops _ =
121133
let list = [[1; 2; 3]; [4; 5; 6]; [7; 8; 9]] in
122134
let a = Vec.of_list <$> Vec.of_list list in
123-
assert_equal (List.flatten list) (Vec.to_list @@ Vec.flatten a);
135+
assert_equal (List.flatten list) (Vec.to_list (Vec.flatten a));
124136

125137
let expected = [1; 1; 1; 2; 2; 2; 3; 3; 3; 4; 4; 4] in
126138
let f i = Vec.of_list [i; i; i] in
127139
let a = 1 -- 4 in
128-
assert_equal expected @@ Vec.to_list (a >>= f)
140+
assert_equal expected (Vec.to_list (a >>= f))
129141

130142
let filter _ =
131143
let v = 0 -- 10 in
132144
let even i = i mod 2 = 0 in
133-
assert_equal [0; 2; 4; 6; 8; 10] (Vec.to_list @@ Vec.filter even v);
134-
assert_equal (Vec.length v) (Vec.length @@ Vec.filteri (=) v);
145+
assert_equal [0; 2; 4; 6; 8; 10] (Vec.to_list (Vec.filter even v));
146+
assert_equal (Vec.length v) (Vec.length (Vec.filteri (=) v));
135147

148+
let old_capacity = Vec.capacity v in
136149
Vec.filter_in_place even v;
137-
assert_equal 6 (Vec.length v)
150+
assert_equal 6 (Vec.length v);
151+
assert_equal old_capacity (Vec.capacity v)
138152

139153
let conversions _ =
140154
let l = [1; 2; 3; 4; 5] in
@@ -149,7 +163,7 @@ let conversions _ =
149163
let rev _ =
150164
let l = [1; 2; 3; 4; 5; 6] in
151165
let v = Vec.of_list l in
152-
assert_equal (List.rev l) (Vec.to_list @@ Vec.rev v);
166+
assert_equal (List.rev l) (Vec.to_list (Vec.rev v));
153167

154168
Vec.rev_in_place v;
155169
assert_equal (List.rev l) (Vec.to_list v)
@@ -167,24 +181,24 @@ let append _ =
167181
assert_equal l (Vec.to_list v');
168182
assert_equal 10 (Vec.length v');
169183

170-
assert_equal l (Vec.to_list @@ v @ v2)
184+
assert_equal l (Vec.to_list (v @ v2))
171185

172186
let exists _ =
173187
let v = Vec.of_list [1; 2; 3; 4; 5] in
174188
assert_bool "exists" (Vec.exists ((=) 4) v);
175189
assert_bool "not exists" (not (Vec.exists ((=) 6) v));
176-
assert_bool "exists empty" (not (Vec.exists (fun _ -> true) @@ Vec.make ()))
190+
assert_bool "exists empty" (not (Vec.exists (fun _ -> true) (Vec.make ())))
177191

178192
let for_all _ =
179193
let v = 5 -- 1 in
180194
assert_bool "for_all" (Vec.for_all ((<=) 1) v);
181195
assert_bool "not for_all" (not (Vec.for_all ((<=) 3) v));
182-
assert_bool "for_all empty" (Vec.for_all (fun _ -> false) @@ Vec.make ())
196+
assert_bool "for_all empty" (Vec.for_all (fun _ -> false) (Vec.make ()))
183197

184198
let mem _ =
185199
let v = 1 -- 100 in
186200
assert_bool "mem" (Vec.mem 95 v);
187-
assert_bool "mem not" (not @@ Vec.mem 101 v);
201+
assert_bool "mem not" (not (Vec.mem 101 v));
188202

189203
let a = [|1; 2|] in
190204
let b = [|1; 2|] in
@@ -214,13 +228,13 @@ let zip _ =
214228
let b = 4 -- 6 in
215229

216230
let expected = [1, 4; 2, 5; 3, 6] in
217-
assert_equal expected (Vec.to_list @@ Vec.zip a b);
231+
assert_equal expected (Vec.to_list (Vec.zip a b));
218232

219233
let expected = [5; 7; 9] in
220-
assert_equal expected (Vec.to_list @@ Vec.zip_with (+) a b)
234+
assert_equal expected (Vec.to_list (Vec.zip_with (+) a b))
221235

222236
let equal _ =
223-
assert_bool "equal empty" @@ Vec.equal (Vec.make ()) (Vec.make ());
237+
assert_bool "equal empty" (Vec.equal (Vec.make ()) (Vec.make ()));
224238

225239
let a = Vec.of_list [1; 2; 3; 4; 5] in
226240
let b = 1 -- 5 in
@@ -235,7 +249,7 @@ let equal _ =
235249
assert_bool "equal diff length" (not (Vec.equal a b))
236250

237251
let compare _ =
238-
assert_equal 0 @@ Vec.compare (Vec.make ()) (Vec.make ());
252+
assert_equal 0 (Vec.compare (Vec.make ()) (Vec.make ()));
239253

240254
let a = Vec.of_list ['a'; 'b'; 'c'] in
241255
let b = Vec.of_list ['a'; 'b'; 'd'] in
@@ -255,21 +269,22 @@ let compare _ =
255269
let pretty_print _ =
256270
let pp = Vec.pretty_print Int.to_string in
257271

258-
assert_equal "[]" (pp @@ Vec.make ());
259-
assert_equal "[2]" (pp @@ Vec.singleton 2);
260-
assert_equal "[1; 2; 3; 4; 5]" (pp @@ 1 -- 5);
272+
assert_equal "[]" (pp (Vec.make ()));
273+
assert_equal "[2]" (pp (Vec.singleton 2));
274+
assert_equal "[1; 2; 3; 4; 5]" (pp (1 -- 5));
261275

262276
let pp = Vec.pretty_print (fun s -> s) in
263-
assert_equal "[abc; def]" (pp @@ Vec.of_list ["abc"; "def"]);
277+
assert_equal "[abc; def]" (pp (Vec.of_list ["abc"; "def"]));
264278

265-
let pp = Vec.pretty_print (fun s -> Int.to_string @@ String.length s) in
266-
assert_equal "[3; 4; 5]" (pp @@ Vec.of_list ["aaa"; "abcd"; "abcde"])
279+
let pp = Vec.pretty_print (fun s -> Int.to_string (String.length s)) in
280+
assert_equal "[3; 4; 5]" (pp (Vec.of_list ["aaa"; "abcd"; "abcde"]))
267281

268282
let test_suite =
269283
"Tests" >:::
270284
[ "make" >:: make
271285
; "capacity" >:: capacity
272286
; "get_set" >:: get_set
287+
; "range" >:: range
273288
; "find" >:: find
274289
; "insert_remove" >:: insert_remove
275290
; "push_pop" >:: push_pop

0 commit comments

Comments
 (0)