-
Notifications
You must be signed in to change notification settings - Fork 13
Open
Description
Goal: Want to have a handler to be executed when a promise is restored within a function, e.g. after await()/yield() calls.
Related current exit calls:
As for the three kinds of exits, I think we could just have:
stop()for errors
return()for normal exit, and
yield()/await()for continuation
Current enter calls:
local()- Setup now. Cleanup on function exit:stop(),return().
Missing enter calls:
- Setup now and on continuation. Cleanup on step exit:
stop(),return(),yield(),await().
Proposal: Add coro::setup(expr)
- It will execute
exprbefore of every coro step (within the defined async function). - Items that are added with
local_*()withinexprare reverted at the end of that step.
This will give us access to both setup/teardown abilities for each step of the coro promise.
Other APIs to considered:
on_step(expr)?with_step(expr)?step_setup(expr)?- ... something
steprelated
Other API names rejected
entry(expr)- to similar toon.exit()which only happens once, where we want to have this method called many times.reentry(expr)- Implies no initial execution
Reprex problem:
the <- new.env(parent = emptyenv())
the$x <- 0
async_ex <- coro::async(function(x) {
old_x <- the$x
the$x <- x
withr::defer({
the$x <- old_x
})
cli::cli_inform("Before await: {the$x}, {x}")
await(coro::async_sleep(0.01))
cli::cli_inform("After await: {the$x}, {x}")
})
async_ex(1)
#> Before await: 1, 1
cli::cli_inform("x: {the$x}")
#> x: 1
async_ex(2)
#> Before await: 2, 2
cli::cli_inform("x: {the$x}")
#> x: 2
while(!later::loop_empty()) later::run_now()
#> After await: 2, 1
#> After await: 0, 2
cli::cli_inform("x: {the$x}")
#> x: 1Created on 2025-09-22 with reprex v2.1.1
(The example above just happened to not work as the promises were finished out of order. 😞 )
Proposal example:
the <- new.env(parent = emptyenv())
the$x <- 0
async_exec_proposal <- coro::async(function(x) {
# Run "now" and again after the `await()`
coro::setup({
old_x <- the$x
the$x <- x
# Run's when "this" coro step is _done_
withr::defer({
the$x <- old_x
})
})
cli::cli_inform("Before await: {the$x}, {x}")
await(coro::async_sleep(0.01))
cli::cli_inform("After await: {the$x}, {x}")
})
async_exec_proposal(1)
#> Before await: 1, 1
cli::cli_inform("x: {the$x}")
#> x: 0
async_exec_proposal(2)
#> Before await: 2, 2
cli::cli_inform("x: {the$x}")
#> x: 0
while(!later::loop_empty()) later::run_now()
#> After await: 1, 1
#> After await: 2, 2
cli::cli_inform("x: {the$x}")
#> x: 0Notice how x would be reset to 0 at all times outside of the async func.
Metadata
Metadata
Assignees
Labels
No labels