[R] chaining closure arguments on-the-fly
Duncan Murdoch
murdoch@dunc@n @end|ng |rom gm@||@com
Sun Jun 21 22:48:22 CEST 2020
On 21/06/2020 11:37 a.m., Benjamin Tyner wrote:
> 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.
I would still say that's a bad idea. The defaults for a function's
arguments are decided by the function's author, so it makes sense for
them to be evaluated in the evaluation frame of the function. The
actual arguments given to the function are decided by whoever calls it,
so they should be evaluated in the caller's environment. That's
standard evaluation.
What you're trying to do mixes up these things: you want the caller to
be able to evaluate things that depend on function internals. That is
bad, because it means the function can no longer be a black box that
does what it is documented to do: it also needs to do it in exactly the
way it did when the caller wrote g(expr), or that could give a garbage
value. Effectively you've broken the encapsulation that functions give
you. You've made f() part of whatever function calls it (but imposed
the rule that says the source of f() can't be modified, which makes no
sense).
Duncan Murdoch
More information about the R-help
mailing list