From 9aae33d56402661913b1630b13127bf13dbb1f96 Mon Sep 17 00:00:00 2001 From: sergeych Date: Fri, 8 Aug 2025 19:33:17 +0300 Subject: [PATCH] fix #48 flows --- docs/parallelism.md | 15 ++++++++++++--- .../kotlin/net/sergeych/lyng/obj/ObjFlow.kt | 4 ---- .../src/commonTest/kotlin/CoroutinesTest.kt | 18 +++++------------- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/docs/parallelism.md b/docs/parallelism.md index c1f0c0e..ab14c8c 100644 --- a/docs/parallelism.md +++ b/docs/parallelism.md @@ -160,23 +160,32 @@ Great: the generator is not executed until collected bu the `f.take()` call, whi Important difference from the channels or like, every time you collect the flow, you collect it anew: + var isStarted = false val f = flow { emit("start") + isStarted = true (1..4).forEach { emit(it) } } + // flow is not yet started, e.g. not got execited, + // that is called 'cold': + assertEquals( false, isStarted ) + // let's collect flow: val result = [] for( x in f ) result += x println(result) - // let's collect it once again: + assertEquals( true, isStarted) + + // let's collect it once again, it should be the same: println(f.toList()) // and again: - //assertEquals( result, f.toList() ) + assertEquals( result, f.toList() ) >>> ["start", 1, 2, 3, 4] >>> ["start", 1, 2, 3, 4] >>> void -1 +Notice that flow's lambda is not called until actual collection is started. Cold flows are +better in terms of resource consumption. diff --git a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjFlow.kt b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjFlow.kt index 6707214..c05d062 100644 --- a/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjFlow.kt +++ b/lynglib/src/commonMain/kotlin/net/sergeych/lyng/obj/ObjFlow.kt @@ -23,10 +23,7 @@ class ObjFlowBuilder(val output: SendChannel) : Obj() { val type = object : ObjClass("FlowBuilder") {}.apply { addFn("emit") { val data = requireOnlyArg() - println("well well $data") try { - println("builder ${thisAs().hashCode()}") - println("channel ${thisAs().output.hashCode()}") val channel = thisAs().output if( !channel.isClosedForSend ) channel.send(data) @@ -74,7 +71,6 @@ class ObjFlow(val producer: Statement) : Obj() { } }.apply { addFn("iterator") { - println("called iterator!") ObjFlowIterator(thisAs().producer) } } diff --git a/lynglib/src/commonTest/kotlin/CoroutinesTest.kt b/lynglib/src/commonTest/kotlin/CoroutinesTest.kt index d149878..d1c951a 100644 --- a/lynglib/src/commonTest/kotlin/CoroutinesTest.kt +++ b/lynglib/src/commonTest/kotlin/CoroutinesTest.kt @@ -90,28 +90,20 @@ class TestCoroutines { fun testFlow2() = runTest { eval(""" val f = flow { - println("Starting generator") emit("start") emit("start2") - println("Emitting") (1..4).forEach { -// println("you hoo "+it) emit(it) } - println("Done emitting") } // let's collect flow: val result = [] -// for( x in f ) result += x - println(result) - + for( x in f ) result += x + println(result) + // let's collect it once again: - println(f.toList()) - println(f.toList()) -// for( x in f ) println(x) -// for( x in f ) println(x) - - //assertEquals( result, f.toList() ) + assertEquals( result, f.toList()) + assertEquals( result, f.toList()) """.trimIndent()) } } \ No newline at end of file