diff --git a/src/FSharp.Control.AsyncSeq/AsyncSeq.fs b/src/FSharp.Control.AsyncSeq/AsyncSeq.fs index f99732b..48d53c5 100644 --- a/src/FSharp.Control.AsyncSeq/AsyncSeq.fs +++ b/src/FSharp.Control.AsyncSeq/AsyncSeq.fs @@ -795,14 +795,32 @@ module AsyncSeq = // -------------------------------------------------------------------------- // Additional combinators (implemented as async/asyncSeq computations) + // Optimized mapAsync enumerator that avoids computation builder overhead + type private OptimizedMapAsyncEnumerator<'T, 'TResult>(source: IAsyncEnumerator<'T>, f: 'T -> Async<'TResult>) = + let mutable disposed = false + + interface IAsyncEnumerator<'TResult> with + member _.MoveNext() = async { + let! moveResult = source.MoveNext() + match moveResult with + | None -> return None + | Some value -> + let! mapped = f value + return Some mapped + } + + member _.Dispose() = + if not disposed then + disposed <- true + source.Dispose() + let mapAsync f (source : AsyncSeq<'T>) : AsyncSeq<'TResult> = match source with | :? AsyncSeqOp<'T> as source -> source.MapAsync f | _ -> - asyncSeq { - for itm in source do - let! v = f itm - yield v } + { new IAsyncEnumerable<'TResult> with + member _.GetEnumerator() = + new OptimizedMapAsyncEnumerator<'T, 'TResult>(source.GetEnumerator(), f) :> IAsyncEnumerator<'TResult> } let mapiAsync f (source : AsyncSeq<'T>) : AsyncSeq<'TResult> = asyncSeq { let i = ref 0L