-
Notifications
You must be signed in to change notification settings - Fork 57
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
Nested member functions & recursive self
-binding
#234
Comments
Oh, I faced exactly the same issue today. Is there any other workaround? Is there a way to access the enclosing "parent" environment from
|
A workaround is to declare those nested functions at the top level of Here's an example of the second approach. I've edited it from my original post, which wouldn't work with classes that had private methods. For the first approach, see your post on SO: https://stackoverflow.com/q/77477472 . library(R6)
Person <- R6Class("Person",
public = list(
name = NULL,
level1 = list(
level2 = list(
level3 = list()
)
),
initialize = function(name) {
self$name = name
self$level1$level2$level3$method <-
private$makeMethod(function() {
print(self$name)
})
}
),
private = list(
makeMethod = function(f) {
env <- new.env(parent = environment(f))
myenv <- parent.env(environment())
for (name in ls(myenv))
env[[name]] <- get(name, envir = myenv)
environment(f) <- env
f
}
)
)
jay = Person$new(name = "Jay")
jay$level1$level2$level3$method()
#> [1] "Jay" Created on 2023-11-14 with reprex v2.0.2 |
Thanks for your replies and approaches. I'm rather fond of the one on the SO. Do you think it's an ok-ish idea to develop a package using this approach? |
I think the SO one is really likely to survive R6 and R updates. A harder question is whether that's a good way to define a class. An alternative would be to replace the nested list with a single public method, called as |
I prefer it because of the syntax. I'm mimicking a Python API package, which has nested attributes/methods. E.g., I'm trying to represent a Python method call Of course, one workaround would be simply calling methods in R in the following manner |
Btw, if I'm not mistaken, Reference Classes have the same issue, no no-go there as well. |
I think this counts as a feature request, unless there's a simple pattern that exists to achieve the desired result that I haven't yet stumbled upon. I've found some instances where it'd be useful to 'nest' methods (mostly for clean naming, sometimes in codegen situations). In spirit, something like this, where
f1
is not a proper member function, but instead a function within a member field:But the
self
environment-binding during construction only seesfunlist
as a list, not as a container of objects into which one might recurse and continue theself
environment-binding. (Same observation for any other named & bound environments, likeprivate
.)One way around this would be implement a special type of
list
, something akin to (or exactly):Now, when examining a new instance's members to determine if each is a data field or method for
self
-binding, one could recurse in the special case of a"R6.memberlist"
field:I realize this is pretty specialized behavior, but ES6 Classes have a few ways to achieve this, including arrow functions (since an arrowfun's
this
is bound to the syntactically-defined container wrapping the function):(There are other ways to use
.bind(...)
to get there, too, but they start to feel pretty convoluted.)Again, this feels like pretty low priority and perhaps helps a very small number of R6 users, but also would be a neat extension to allow a tad more flexibility to the
self
/private
-binding process :-)In any case, thanks for all the existing work on R6!
The text was updated successfully, but these errors were encountered: