[R] chaining closure arguments on-the-fly

Bert Gunter bgunter@4567 @end|ng |rom gm@||@com
Sat Jun 20 23:49:06 CEST 2020


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 using 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 using 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]]



More information about the R-help mailing list