have CCList.{get,insert,set}_at_idx work with negative indices

This commit is contained in:
Simon Cruanes 2017-12-25 17:30:00 +01:00
parent d8610646d8
commit 7f6cb0f673
2 changed files with 26 additions and 9 deletions

View file

@ -1068,10 +1068,14 @@ let foldi f acc l =
in in
foldi f acc 0 l foldi f acc 0 l
let rec get_at_idx_exn i l = match l with let rec get_at_idx_rec i l = match l with
| [] -> raise Not_found | [] -> raise Not_found
| x::_ when i=0 -> x | x::_ when i=0 -> x
| _::l' -> get_at_idx_exn (i-1) l' | _::l' -> get_at_idx_rec (i-1) l'
let get_at_idx_exn i l =
let i = if i<0 then length l + i else i in
get_at_idx_rec i l
let get_at_idx i l = let get_at_idx i l =
try Some (get_at_idx_exn i l) try Some (get_at_idx_exn i l)
@ -1081,7 +1085,9 @@ let get_at_idx i l =
get_at_idx 0 (range 0 10) = Some 0 get_at_idx 0 (range 0 10) = Some 0
get_at_idx 5 (range 0 10) = Some 5 get_at_idx 5 (range 0 10) = Some 5
get_at_idx 11 (range 0 10) = None get_at_idx 11 (range 0 10) = None
get_at_idx (-1) (range 0 10) = Some 10
get_at_idx 0 [] = None get_at_idx 0 [] = None
get_at_idx (-1) [] = None
*) *)
let set_at_idx i x l0 = let set_at_idx i x l0 =
@ -1091,12 +1097,14 @@ let set_at_idx i x l0 =
| y::l' -> | y::l' ->
aux l' (y::acc) (i-1) aux l' (y::acc) (i-1)
in in
let i = if i<0 then length l0 + i else i in
aux l0 [] i aux l0 [] i
(*$T (*$T
set_at_idx 0 10 [1;2;3] = [10;2;3] set_at_idx 0 10 [1;2;3] = [10;2;3]
set_at_idx 4 10 [1;2;3] = [1;2;3] set_at_idx 4 10 [1;2;3] = [1;2;3]
set_at_idx 1 10 [1;2;3] = [1;10;3] set_at_idx 1 10 [1;2;3] = [1;10;3]
set_at_idx (-2) 10 [1;2;3] = [1;10;3]
*) *)
let insert_at_idx i x l = let insert_at_idx i x l =
@ -1106,12 +1114,14 @@ let insert_at_idx i x l =
| y::l' -> | y::l' ->
aux l' (y::acc) (i-1) x aux l' (y::acc) (i-1) x
in in
let i = if i<0 then length l + i else i in
aux l [] i x aux l [] i x
(*$T (*$T
insert_at_idx 0 10 [1;2;3] = [10;1;2;3] insert_at_idx 0 10 [1;2;3] = [10;1;2;3]
insert_at_idx 4 10 [1;2;3] = [1;2;3;10] insert_at_idx 4 10 [1;2;3] = [1;2;3;10]
insert_at_idx 1 10 [1;2;3] = [1;10;2;3] insert_at_idx 1 10 [1;2;3] = [1;10;2;3]
insert_at_idx (-2) 10 [1;2;3] = [1;10;2;3]
*) *)
let remove_at_idx i l0 = let remove_at_idx i l0 =
@ -1121,9 +1131,7 @@ let remove_at_idx i l0 =
| y::l' -> | y::l' ->
aux l' (y::acc) (i-1) aux l' (y::acc) (i-1)
in in
if i < 0 then let i = if i<0 then length l0 + i else i in
aux l0 [] (List.length l0 + i)
else
aux l0 [] i aux l0 [] i
(*$T (*$T

View file

@ -339,6 +339,9 @@ val foldi : ('b -> int -> 'a -> 'b) -> 'b -> 'a t -> 'b
(** Fold on list, with index *) (** Fold on list, with index *)
val get_at_idx : int -> 'a t -> 'a option val get_at_idx : int -> 'a t -> 'a option
(** Get by index in the list.
If the index is negative, it will get element starting from the end
of the list. *)
val nth_opt : 'a t -> int -> 'a option val nth_opt : 'a t -> int -> 'a option
(** Safe version of {!nth}. (** Safe version of {!nth}.
@ -347,15 +350,21 @@ val nth_opt : 'a t -> int -> 'a option
val get_at_idx_exn : int -> 'a t -> 'a val get_at_idx_exn : int -> 'a t -> 'a
(** Get the i-th element, or (** Get the i-th element, or
@raise Not_found if the index is invalid *) @raise Not_found if the index is invalid
If the index is negative, it will get element starting from the end
of the list. *)
val set_at_idx : int -> 'a -> 'a t -> 'a t val set_at_idx : int -> 'a -> 'a t -> 'a t
(** Set i-th element (removes the old one), or does nothing if (** Set i-th element (removes the old one), or does nothing if
index is too high *) index is too high.
If the index is negative, it will set element starting from the end
of the list. *)
val insert_at_idx : int -> 'a -> 'a t -> 'a t val insert_at_idx : int -> 'a -> 'a t -> 'a t
(** Insert at i-th position, between the two existing elements. If the (** Insert at i-th position, between the two existing elements. If the
index is too high, append at the end of the list *) index is too high, append at the end of the list.
If the index is negative, it will insert element starting from the end
of the list. *)
val remove_at_idx : int -> 'a t -> 'a t val remove_at_idx : int -> 'a t -> 'a t
(** Remove element at given index. Does nothing if the index is (** Remove element at given index. Does nothing if the index is