Skip to content
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

Error when using coro::async as an R6 method: object '_parent' not found #63

Open
dereckmezquita opened this issue Feb 9, 2025 · 0 comments · May be fixed by #64
Open

Error when using coro::async as an R6 method: object '_parent' not found #63

dereckmezquita opened this issue Feb 9, 2025 · 0 comments · May be fixed by #64

Comments

@dereckmezquita
Copy link

When an asynchronous function created with coro::async is used as a method of an R6 class, the function fails with an error indicating that the internal _parent object is missing. It appears that R6’s practice of replacing a method’s environment (to provide self/private) is stripping out the closure variable _parent that the async machinery relies on. This issue is similar in spirit to #30 (which dealt with generators), but now it affects async functions as well.

Minimal Reproducible Example:

#!/usr/bin/env Rscript
options(error = function() {
    rlang::entrace()
    rlang::last_trace()
})

sessionInfo()
print(paste("coro: ", packageVersion("coro")))
print(paste("promises: ", packageVersion("promises")))
print(paste("later: ", packageVersion("later")))
print(paste("rlang: ", packageVersion("rlang")))
print(paste("R6: ", packageVersion("R6")))

api_data <- function() {
    return(promises::promise(function(resolve, reject) {
        later::later(function() {
            resolve("Hello, API!")
        }, delay = 3)
    }))
}

MyAPI <- R6::R6Class("MyAPI",
    public = list(
        getData = coro::async(function() {
            message("Simulating API call...")
            result <- await(api_data())
            return(result)
        })
    )
)

# Create an instance and call the asynchronous method.
api <- MyAPI$new()

api$getData()$
    then(function(data) {
        message("Data received: ", data)
    })$
    catch(function(e) {
        message("Error: ", conditionMessage(e))
    })

# Run the later event loop until all asynchronous tasks are complete.
while (!later::loop_empty()) {
    later::run_now()
}
(base) work@Derecks-MacBook-Air kucoin % Rscript research/r6-coro-async.R
R version 4.4.1 (2024-06-14)
Platform: aarch64-apple-darwin23.4.0
Running under: macOS 15.3

Matrix products: default
BLAS:   /opt/homebrew/Cellar/openblas/0.3.27/lib/libopenblasp-r0.3.27.dylib 
LAPACK: /opt/homebrew/Cellar/r/4.4.1/lib/R/lib/libRlapack.dylib;  LAPACK version 3.12.0

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/Chicago
tzcode source: internal

attached base packages:
[1] stats     graphics  grDevices datasets  utils     methods   base     

loaded via a namespace (and not attached):
[1] compiler_4.4.1 tools_4.4.1    renv_1.0.7    
[1] "coro:  1.1.0"
[1] "promises:  1.3.0"
[1] "later:  1.3.2"
[1] "rlang:  1.1.4"
[1] "R6:  2.5.1"
Error in api$getData() : object '_parent' not found
Calls: <Anonymous> -> <Anonymous> -> dots_split
Backtrace:
    ▆
 1. ├─api$getData()
 2. │ └─rlang::env(`_parent`)
 3. │   └─rlang:::dots_split(..., .n_unnamed = 0:1)
 4. └─global `<fn>`()
Execution halted
(base) work@Derecks-MacBook-Air kucoin % 

My understanding

The problem seems to stem from how coro::async captures its internal _parent environment. When the async function is defined, _parent is available in the closure. However, R6 replaces method environments with its own class environment during instantiation (to provide self and private), and in doing so, it loses the _parent binding that coro::async relies on. Thus, when the async function is later invoked, a call to rlang::env("_parent") fails because _parent is not found.

I would be happy to work on a pull request to implement a change/bug fix. Any guidance is appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant