aboutsummaryrefslogtreecommitdiffstats
path: root/lib/protocols
diff options
context:
space:
mode:
authorMarcos Magueta <maguetamarcos@gmail.com>2026-10-12 11:58:25 -0300
committerMarcos Magueta <maguetamarcos@gmail.com>2026-10-12 11:58:25 -0300
commitad33454a204aa5791445e7d15f02ba0447fff85e (patch)
treeb1730a9ac5b40ff58ddc23976cd5df5dac924231 /lib/protocols
parentd4f603fa04283efe54c79b5f7664c4c9bc193857 (diff)
downloadRNT-ad33454a204aa5791445e7d15f02ba0447fff85e.tar.gz
RNT-ad33454a204aa5791445e7d15f02ba0447fff85e.zip
relation scan with enumerable and release
Diffstat (limited to '')
-rw-r--r--lib/protocols/Cursor.ml2
-rw-r--r--lib/protocols/Cursor.mli6
-rw-r--r--lib/protocols/Enumerable.ml2
-rw-r--r--lib/protocols/Enumerable.mli7
-rw-r--r--lib/protocols/Relation.ml8
5 files changed, 19 insertions, 6 deletions
diff --git a/lib/protocols/Cursor.ml b/lib/protocols/Cursor.ml
index f9bd697..f53bfa1 100644
--- a/lib/protocols/Cursor.ml
+++ b/lib/protocols/Cursor.ml
@@ -39,3 +39,5 @@ let drain i ?(limit = 256) () =
if batch.exhausted then Ok tuples else loop tuples
in
loop BatFingerTree.empty
+
+let consuming cursor f = Handle.releasing cursor (fun () -> Result.bind (require cursor) f)
diff --git a/lib/protocols/Cursor.mli b/lib/protocols/Cursor.mli
index ff6c027..deccf2a 100644
--- a/lib/protocols/Cursor.mli
+++ b/lib/protocols/Cursor.mli
@@ -19,3 +19,9 @@ val drain :
?limit:int ->
unit ->
(Concepts.Tuple.t BatFingerTree.t, Concepts.Condition.condition) result
+
+(** [f] over [cursor], which is released once [f] returns. *)
+val consuming :
+ Handle.t ->
+ (t Handle.interface -> ('a, Concepts.Condition.condition) result) ->
+ ('a, Concepts.Condition.condition) result
diff --git a/lib/protocols/Enumerable.ml b/lib/protocols/Enumerable.ml
index 53db834..76b4e86 100644
--- a/lib/protocols/Enumerable.ml
+++ b/lib/protocols/Enumerable.ml
@@ -19,3 +19,5 @@ let make impl = Enumerable (impl :> implementation)
let from handle = Handle.into handle (function Enumerable impl -> Some impl | _ -> None)
let require handle = from handle |> Option.to_result ~none:(Error.not_enumerable ())
let enumerate i = Handle.invoke i (fun o -> o#enumerate)
+let cursor handle = Result.bind (require handle) enumerate
+let scan handle f = Result.bind (cursor handle) (fun cursor -> Cursor.consuming cursor f)
diff --git a/lib/protocols/Enumerable.mli b/lib/protocols/Enumerable.mli
index 2c0ee69..a0c1f1c 100644
--- a/lib/protocols/Enumerable.mli
+++ b/lib/protocols/Enumerable.mli
@@ -8,3 +8,10 @@ val make : #implementation -> Handle.protocol
val from : Handle.t -> t Handle.interface option
val require : Handle.t -> (t Handle.interface, Concepts.Condition.condition) result
val enumerate : t Handle.interface -> (Handle.t, Concepts.Condition.condition) result
+val cursor : Handle.t -> (Handle.t, Concepts.Condition.condition) result
+
+(** [f] over a cursor on [handle], released once [f] returns. *)
+val scan :
+ Handle.t ->
+ (Cursor.t Handle.interface -> ('a, Concepts.Condition.condition) result) ->
+ ('a, Concepts.Condition.condition) result
diff --git a/lib/protocols/Relation.ml b/lib/protocols/Relation.ml
index c1cdfee..e475919 100644
--- a/lib/protocols/Relation.ml
+++ b/lib/protocols/Relation.ml
@@ -31,9 +31,5 @@ let heading relation =
let read relation =
let open Utilities.Result in
let* heading = heading relation in
- let* enumerable = Enumerable.require relation in
- let* cursor = Enumerable.enumerate enumerable in
- Handle.releasing cursor (fun () ->
- let* scan = Cursor.require cursor in
- let* tuples = Cursor.drain scan () in
- Ok (heading, BatFingerTree.to_list tuples) )
+ let* tuples = Enumerable.scan relation (fun scan -> Cursor.drain scan ()) in
+ Ok (heading, BatFingerTree.to_list tuples)