diff --git a/src/core/CCList.ml b/src/core/CCList.ml index 75684ce0..b5f4c219 100644 --- a/src/core/CCList.ml +++ b/src/core/CCList.ml @@ -823,6 +823,20 @@ let hd_tl = function let take_drop n l = take n l, drop n l +let rec take_last = function + | [] -> failwith "take_last" + | [ x ] -> [], x + | hd :: tl -> + let tl, lt = take_last tl in + hd :: tl, lt + +let rec take_last_opt = function + | [] -> [], None + | [ x ] -> [], Some x + | hd :: tl -> + let tl, lt = take_last_opt tl in + hd :: tl, lt + let sublists_of_len ?(last = fun _ -> None) ?offset n l = if n < 1 then invalid_arg "sublists_of_len: n must be > 0"; let offset = diff --git a/src/core/CCList.mli b/src/core/CCList.mli index d3dc0f94..e8ec87a6 100644 --- a/src/core/CCList.mli +++ b/src/core/CCList.mli @@ -414,6 +414,12 @@ val take_drop_while : ('a -> bool) -> 'a t -> 'a t * 'a t @since 1.2, but only @since 2.2 with labels *) +val take_last : 'a t -> 'a t * 'a +(** [take_last l] = (tl l, last l). *) + +val take_last_opt : 'a t -> 'a t * 'a option +(** [take_last l] = (tl l, last_opt l). *) + val last : int -> 'a t -> 'a t (** [last n l] takes the last [n] elements of [l] (or less if [l] doesn't have that many elements). *) diff --git a/src/core/CCListLabels.mli b/src/core/CCListLabels.mli index 83421d6c..bed5abc4 100644 --- a/src/core/CCListLabels.mli +++ b/src/core/CCListLabels.mli @@ -447,6 +447,12 @@ val take_drop_while : f:('a -> bool) -> 'a t -> 'a t * 'a t @since 1.2, but only @since 2.2 with labels *) +val take_last : 'a t -> 'a t * 'a +(** [take_last l] = (tl l, last l). *) + +val take_last_opt : 'a t -> 'a t * 'a option +(** [take_last l] = (tl l, last_opt l). *) + val last : int -> 'a t -> 'a t (** [last n l] takes the last [n] elements of [l] (or less if [l] doesn't have that many elements). *) diff --git a/tests/core/t_list.ml b/tests/core/t_list.ml index 70e36b6d..e0b2257a 100644 --- a/tests/core/t_list.ml +++ b/tests/core/t_list.ml @@ -807,6 +807,13 @@ t @@ fun () -> take_while (fun x -> x <> 0) [ 0; 1; 2; 3 ] = [];; t @@ fun () -> take_while (fun _ -> true) [] = [];; t @@ fun () -> take_while (fun _ -> true) (1 -- 10) = 1 -- 10;; t @@ fun () -> take_while (fun _ -> true) (1 -- 300_000) = 1 -- 300_000;; +t @@ fun () -> take_last [ 1 ] = ([], 1);; +t @@ fun () -> take_last [ 1; 2; 3; 4; 5 ] = ([ 1; 2; 3; 4 ], 5);; +t @@ fun () -> take_last (1 -- 10_000) = (1 -- 9_999, 10_000);; +t @@ fun () -> take_last_opt [] = ([], None);; +t @@ fun () -> take_last_opt [ 1 ] = ([], Some 1);; +t @@ fun () -> take_last_opt [ 1; 2; 3; 4; 5 ] = ([ 1; 2; 3; 4 ], Some 5);; +t @@ fun () -> take_last_opt (1 -- 10_000) = (1 -- 9_999, Some 10_000);; q Q.(pair (fun1 Observable.int bool) (list small_int))