package async_kernel
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
Monadic concurrency library
Install
dune-project
Dependency
Authors
Maintainers
Sources
v0.17.0.tar.gz
sha256=01ced973dbc70535f692f38bed524ae82dba17e26e58791b2fbf0d647b160d2e
doc/src/async_kernel/deferred_sequence.ml.html
Source file deferred_sequence.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 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200open Core open Deferred_std module Deferred = Deferred1 (* [fold_mapi ~how t ~init ~mapi_f ~fold_f] is a more efficient version of: {[ fold ~init ~f:(fun b a -> return (fold_f b a)) (mapi t ~how ~f:mapi_f) ]} It avoids creating the intermediate sequence that would result from [mapi], and allows the [fold] to proceed concurrently with the [mapi], so that one can accumulate the result as soon as possible, possibly avoiding creating an intermediate structure (e.g. [iteri] and [filter_map] uses [fold_mapi] to do this). *) let fold_mapi (type a b c) ?(how = `Sequential) (t : a Sequence.t) ~(init : c) ~(mapi_f : int -> a -> b Deferred.t) ~(fold_f : c -> b -> c) : c Deferred.t = let%tydi (Sequence { state; next }) = Sequence.Expert.view t in match how with | `Sequential -> let result = Ivar.create () in let rec loop i state (c : c) = match next state with | Done -> Ivar.fill_exn result c | Skip { state } -> loop i state (c : c) | Yield { state; value = a } -> upon (mapi_f i a) (fun b -> loop (i + 1) state (fold_f c b)) in loop 0 state init; Ivar.read result | `Parallel -> let rec loop i t (c : c Deferred.t) = match next t with | Done -> c | Skip { state } -> loop i state c | Yield { value = a; state = t } -> loop (i + 1) t (let%bind b = mapi_f i a in let%map c = c in fold_f c b) in loop 0 state (return init) | `Max_concurrent_jobs max_concurrent_jobs -> let throttle = Throttle.create ~max_concurrent_jobs ~continue_on_error:false in (* [loop] forces the input sequence and enqueues a throttle job only if there is capacity available. *) let rec loop i t (c : c Deferred.t) = let%bind () = Throttle.capacity_available throttle in match next t with | Done -> c | Skip { state } -> loop i state c | Yield { value = a; state = t } -> loop (i + 1) t (let%bind b = Throttle.enqueue throttle (fun () -> mapi_f i a) in let%map c = c in fold_f c b) in loop 0 state (return init) ;; let foldi t ~init ~f = Sequence.delayed_fold t ~init:(0, init) ~f:(fun (i, b) a ~k -> let%bind b = f i b a in k (i + 1, b)) ~finish:(fun (_, b) -> return b) ;; (* [fold] is not implemented in terms of [foldi] to save the intermediate closure allocation. *) let fold t ~init ~f = Sequence.delayed_fold t ~init ~f:(fun b a ~k -> f b a >>= k) ~finish:return ;; let all t = let%map res = fold t ~init:[] ~f:(fun accum d -> let%map a = d in a :: accum) in Sequence.of_list (List.rev res) ;; let all_unit t = fold t ~init:() ~f:(fun () v -> v) let find_mapi t ~f = let rec find_mapi t ~f i = match Sequence.next t with | None -> return None | Some (v, rest) -> (match%bind f i v with | None -> find_mapi rest ~f (i + 1) | Some _ as some -> return some) in find_mapi t ~f 0 ;; let findi t ~f = find_mapi t ~f:(fun i elt -> let%map b = f i elt in if b then Some (i, elt) else None) ;; let find t ~f = find_mapi t ~f:(fun _ elt -> let%map b = f elt in if b then Some elt else None) ;; let existsi t ~f = match%map find_mapi t ~f:(fun i elt -> let%map b = f i elt in if b then Some () else None) with | Some () -> true | None -> false ;; let for_alli t ~f = match%map find_mapi t ~f:(fun i elt -> let%map b = f i elt in if not b then Some () else None) with | Some () -> false | None -> true ;; let iteri ~how t ~f : unit Deferred.t = fold_mapi ~how t ~mapi_f:f ~init:() ~fold_f:(fun () () -> ()) ;; let mapi ~how t ~f = let%map bs = fold_mapi ~how t ~mapi_f:(fun i a -> f i a) ~init:[] ~fold_f:(fun bs b -> b :: bs) in Sequence.of_list (List.rev bs) ;; (* [filter_mapi] is implemented using [fold_mapi] rather than [map] so that we never need to keep a long stream of intermediate [None] results in the accumulator, only to later filter them all out. *) let filter_mapi ~how t ~f = let%map bs = fold_mapi t ~how ~mapi_f:(fun i a -> f i a) ~init:[] ~fold_f:(fun bs maybe_v -> match maybe_v with | None -> bs | Some b -> b :: bs) in Sequence.of_list (List.rev bs) ;; let concat_mapi ~how t ~f = mapi ~how t ~f >>| Sequence.concat let filteri ~how t ~f = filter_mapi ~how t ~f:(fun i a -> match%map f i a with | true -> Some a | false -> None) ;; let iter ~how t ~f = iteri ~how t ~f:(fun _ a -> f a) let map ~how t ~f = mapi ~how t ~f:(fun _ a -> f a) let filter ~how t ~f = filteri ~how t ~f:(fun _ a -> f a) let filter_map ~how t ~f = filter_mapi ~how t ~f:(fun _ a -> f a) let concat_map ~how t ~f = concat_mapi ~how t ~f:(fun _ a -> f a) let find_map t ~f = find_mapi t ~f:(fun _ a -> f a) let exists t ~f = existsi t ~f:(fun _ a -> f a) let for_all t ~f = for_alli t ~f:(fun _ a -> f a) let init ~how n ~f = map ~how (Sequence.init n ~f:Fn.id) ~f let count ?how t ~f = fold_mapi ?how t ~mapi_f:(fun _i a -> f a) ~init:0 ~fold_f:(fun acc c -> acc + Bool.to_int c) ;; let sum (type a) (module M : Base.Container.Summable with type t = a) ?how t ~f = fold_mapi ?how t ~mapi_f:(fun _i a -> f a) ~init:M.zero ~fold_f:M.( + ) ;;
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>