diff --git a/src/core/CCOpt.ml b/src/core/CCOpt.ml index 76d0d9ad..2d03c29a 100644 --- a/src/core/CCOpt.ml +++ b/src/core/CCOpt.ml @@ -153,6 +153,25 @@ type 'a random_gen = Random.State.t -> 'a let random g st = if Random.State.bool st then Some (g st) else None +exception ExitChoice + +let choice_seq s = + let r = ref None in + begin try + s (function + | None -> () + | (Some _) as o -> r := o; raise ExitChoice + ) + with ExitChoice -> () + end; + !r + +(*$T + choice_seq (Sequence.of_list [None; Some 1; Some 2]) = Some 1 + choice_seq Sequence.empty = None + choice_seq (Sequence.repeat None |> Sequence.take 100) = None +*) + let to_gen o = match o with | None -> (fun () -> None) diff --git a/src/core/CCOpt.mli b/src/core/CCOpt.mli index 1093dbe8..e5409020 100644 --- a/src/core/CCOpt.mli +++ b/src/core/CCOpt.mli @@ -126,6 +126,11 @@ type 'a random_gen = Random.State.t -> 'a val random : 'a random_gen -> 'a t random_gen +val choice_seq : 'a t sequence -> 'a t +(** [choice_seq s] is similar to {!choice}, but works on sequences. + It returns the first [Some x] occurring in [s], or [None] otherwise. + @since NEXT_RELEASE *) + val to_gen : 'a t -> 'a gen val to_seq : 'a t -> 'a sequence