On 6/20/20 9:00 AM, Duncan Murdoch wrote:> How about > > g <- function(x, y = x) { > ? f(x, y) > } > g(x = 3) > > or even > > yEqualsX <- function(f) function(x, y = x) f(x, y) > > yEqualsX(f)(x = 3) > > These are a lot like currying, but aren't currying, so they may be > acceptable to you.? Personally I'd choose the first one. > > Duncan Murdoch >Thank you Duncan; I should have been more explicit that I was also trying to avoid defining any new functions, but yes, it's hard to argue with the wrapper approach as a longstanding best practice. Basically I'm wondering if it would be theoretically possible to construct a function "g" (possibly it would have to be primitive/internal) such that f(x = 3, y = g(expr)) would evaluate expr in the evaluation environment of f? After rereading section 4.3.3 of the R Language Definition, it's clear that supplied arguments are evaluated in the calling environment; though trickery in f()'s body may be used to evaluate elsewhere, such options seem limited from within the argument list itself. Ben
On 20/06/2020 4:44 p.m., Benjamin Tyner wrote:> On 6/20/20 9:00 AM, Duncan Murdoch wrote: >> How about >> >> g <- function(x, y = x) { >> ? f(x, y) >> } >> g(x = 3) >> >> or even >> >> yEqualsX <- function(f) function(x, y = x) f(x, y) >> >> yEqualsX(f)(x = 3) >> >> These are a lot like currying, but aren't currying, so they may be >> acceptable to you.? Personally I'd choose the first one. >> >> Duncan Murdoch >> > Thank you Duncan; I should have been more explicit that I was also > trying to avoid defining any new functions, but yes, it's hard to argue > with the wrapper approach as a longstanding best practice. > > Basically I'm wondering if it would be theoretically possible to > construct a function "g" (possibly it would have to be > primitive/internal) such that > > f(x = 3, y = g(expr)) > > would evaluate expr in the evaluation environment of f? After rereading > section 4.3.3 of the R Language Definition, it's clear that supplied > arguments are evaluated in the calling environment; though trickery in > f()'s body may be used to evaluate elsewhere, such options seem limited > from within the argument list itself.I think you effectively did that in your original post (all but encapsulating the expression in a function), so yes, it's possible. However, it's a really bad idea. Why use non-standard evaluation when standard evaluation is fine? Standard evaluation follows some well defined rules, and is easy to reason about. NSE follows whatever rules it wants, so it's really hard for users to follow. For example, assuming you had the g() you want, what would this give? z <- 3 f(x = z, y = g(z)) You can't possibly know that without knowing whether there's a local variable in f named z that is created before y is evaluated. Duncan Murdoch
Gents: (with trepidation) f(x = 3, y = g(expr)) **already** evaluates g in the environment of f, **not** in the environment of the caller. (This does not contradict Duncan's example -- 3 is a constant, not a variable). e.g.> f <- function(x = 3, y = x^2 +k){+ k <- 3 + x + y + } Ergo> k <- 100; x <- 10 > f()[1] 15> f(0)[1] 3> x[1] 10 This is all due to lazy evaluation where default arguments are evaluated in the function's environment (using standard evaluation). Arguments supplied in the call are evaluated in the caller's environment, so:> f(x = x)[1] 113 Am I missing something here? Cheers, Bert Gunter "The trouble with having an open mind is that people keep coming along and sticking things into it." -- Opus (aka Berkeley Breathed in his "Bloom County" comic strip ) On Sat, Jun 20, 2020 at 2:05 PM Duncan Murdoch <murdoch.duncan at gmail.com> wrote:> On 20/06/2020 4:44 p.m., Benjamin Tyner wrote: > > On 6/20/20 9:00 AM, Duncan Murdoch wrote: > >> How about > >> > >> g <- function(x, y = x) { > >> f(x, y) > >> } > >> g(x = 3) > >> > >> or even > >> > >> yEqualsX <- function(f) function(x, y = x) f(x, y) > >> > >> yEqualsX(f)(x = 3) > >> > >> These are a lot like currying, but aren't currying, so they may be > >> acceptable to you. Personally I'd choose the first one. > >> > >> Duncan Murdoch > >> > > Thank you Duncan; I should have been more explicit that I was also > > trying to avoid defining any new functions, but yes, it's hard to argue > > with the wrapper approach as a longstanding best practice. > > > > Basically I'm wondering if it would be theoretically possible to > > construct a function "g" (possibly it would have to be > > primitive/internal) such that > > > > f(x = 3, y = g(expr)) > > > > would evaluate expr in the evaluation environment of f? After rereading > > section 4.3.3 of the R Language Definition, it's clear that supplied > > arguments are evaluated in the calling environment; though trickery in > > f()'s body may be used to evaluate elsewhere, such options seem limited > > from within the argument list itself. > > I think you effectively did that in your original post (all but > encapsulating the expression in a function), so yes, it's possible. > However, it's a really bad idea. Why use non-standard evaluation when > standard evaluation is fine? Standard evaluation follows some well > defined rules, and is easy to reason about. NSE follows whatever rules > it wants, so it's really hard for users to follow. For example, > assuming you had the g() you want, what would this give? > > z <- 3 > f(x = z, y = g(z)) > > You can't possibly know that without knowing whether there's a local > variable in f named z that is created before y is evaluated. > > Duncan Murdoch > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]
On 6/20/20 5:04 PM, Duncan Murdoch wrote:> I think you effectively did that in your original post (all but > encapsulating the expression in a function), so yes, it's possible. > However, it's a really bad idea.? Why use non-standard evaluation when > standard evaluation is fine?? Standard evaluation follows some well > defined rules, and is easy to reason about.? NSE follows whatever > rules it wants, so it's really hard for users to follow.? For example, > assuming you had the g() you want, what would this give? > > z <- 3 > f(x = z, y = g(z)) > > You can't possibly know that without knowing whether there's a local > variable in f named z that is created before y is evaluated. > > Duncan Murdoch > >Very good point, and I agree it's best to use standard evaluation whenever possible. The role of g would essentially be to modify one or more elements of f's formals in-place. For example calling: f(x = 3, y = g(expr)) would be equivalent to calling a function fm: fm(x = 3) where the body of fm is identical to that of f, but: > formals(fm) $x $y expr though I expect g would be non-trivial to code up robustly.