-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement parameterize
as multi-shot coroutine
#34
Comments
There may be some fundamental issues with this as well, since it'd be breaking assumptions that Kotlin makes about code. For example: suspend fun multiResume() {}
suspend fun x() {
val a: Int
multiResume()
a = 4
a = 5 // ERROR: 'val' cannot be reassigned
} Here Kotlin is fine with the first assignment since it assumes that the continuation at Testing on JVM I'm finding that the code does run without any issue, replacing the value of 4 with 5. There are some subtle inconsistencies that can arise though: fun test() {
val a: Int
a = 4
val printCaptured = { println(a) }
@Suppress("VAL_REASSIGNMENT")
a = 5
printCaptured()
println(a)
} In this example, a is captured in the lambda, and since it's a val and won't change, the constant value While this isn't necessarily a problem, and might even be desirable, it might hint towards a bigger issue when abusing coroutines like this. |
I got nerd-sniped by this, and have now opened #37 I have a project in the works that implements multishot coroutines in Kotlin. What Kotlin provides is usually termed "single-shot delimited continuations" in academia. It's a well-known academia result that multishot delimited continuations can do "monadic reflection", which is a fancy term for being able to write monadic code in direct style (which is way better than e.g. for-comprehensions or do-notation).
No need for
Obviously, if
This reveals the implementation detail that The other way is to somehow still store
now every access to context("group") {
parameterize {
// ...
test("test") { // suspends with `context`'s coroutine scope, through parameterize's
val x by parameter(...)
}
}
} This can cause a bunch of unintended consequences depending how |
The intended usage is: context("group") {
parameterize {
val x by parameter(...)
// ...
test("test") { // suspends with `context`'s coroutine scope, through parameterize's
}
val y by parameter(...)
test("test 2 $y") { … }
}
} As long as this is supported, I think it isn't a problem if declaring parameters within non- |
Yeah that intended usage is absolutely fine! It's not even about Using |
Sorry for the late reply! I've been pretty busy and haven't had time to appreciate this yet. I wanted to mention quick that I just opened an issue for allowing |
Take all the time you need! Feel free to ask any questions or anything like that. |
This is not a planned feature, at least not yet, but this issue tracks how
parameterize
could work if it were implemented as asuspend
block that resumes from eachparameter
instead of re-running the whole blockIt could be implemented as a suspend point when declaring a parameter:
A
parameter
will be constructed only once (instead of every iteration). After that, there will be a suspend point whenprovideDelegate
is called on it, and having the listed/computed arguments locked in. From there,parameterize
'ssuspend
block will resume from there once for each of the arguments as a multi-shot coroutine.Benefits
ParameterizeContinue
up the call stack for internal control flowparameterOf
is no longer a performance concernparameterize
is no longer neededProblems/Blockers
provideDelegate
as suspend is not supported as of Kotlin 2.0Implementation
Multi-shot coroutines should be possible as long as a coroutine continuation can be cloned, that way it can be resumed more than once.
For each platform:
The text was updated successfully, but these errors were encountered: