From b687d34ea2c78386a6026bd9d1f7b682852d8200 Mon Sep 17 00:00:00 2001 From: XperiAndri Date: Mon, 5 Oct 2026 02:12:29 +0200 Subject: [PATCH] feat(observable): add `chunkByBoundaries` for boundaries of any element type `ChunkWindowBoundaries` reuses the element type of the source for the boundary sequence, although R3 ignores the boundary values, so chunking by `Observable` ticks or a trigger subject required a dummy `map`. `chunkByBoundaries` passes boundaries of any element type to R3. Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 1 + src/FSharp.Control.R3/Observable.fs | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ed6f2f..abffcbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `Observable.choose` as a function of the `Observable` module; like every function of the library that works with optional values it takes a `voption` chooser, and the `option` variant is `ObservableOption.choose` - `Observable.ofSeq (items)` and `Observable.ofSeq (items, cancellationToken)`, reachable after `open FSharp.Control.R3` +- `Observable.chunkByBoundaries` accepting window boundaries of any element type - `rxqueryWith cancellationToken` and `RxQueryBuilder (cancellationToken)` to cancel the query operators that return a task ### Changed diff --git a/src/FSharp.Control.R3/Observable.fs b/src/FSharp.Control.R3/Observable.fs index 551a998..4d49ef3 100644 --- a/src/FSharp.Control.R3/Observable.fs +++ b/src/FSharp.Control.R3/Observable.fs @@ -42,6 +42,19 @@ let inline chunkBy (configuration : ChunkConfiguration<'T>) (source) = | ChunkAsyncWindow (asyncWindow, configureAwait) -> ObservableExtensions.Chunk (source, asyncWindow, configureAwait) | ChunkWindowBoundaries windowBoundaries -> ObservableExtensions.Chunk (source, windowBoundaries = windowBoundaries) +// ChunkWindowBoundaries reuses the element type of the source for the boundaries, while R3 ignores the boundary values; +// this function accepts boundaries of any element type, such as Observable ticks +/// +/// Divides the source into chunks that end on every element of . +/// +/// A boundary element emits the buffered elements, or an empty chunk when nothing is buffered. +/// Completion of the source emits the remaining elements; completion of the boundaries, even a failed one, +/// emits the remaining elements and completes the chunked sequence successfully. +/// +/// +let inline chunkByBoundaries (windowBoundaries : Observable<'Boundary>) (source : Observable<'T>) = + ObservableExtensions.Chunk (source, windowBoundaries = windowBoundaries) + /// Returns an observable sequence that only contains distinct elements let inline distinct source = ObservableExtensions.Distinct source