[R] Function in default parameter value closing over variables defined later in the enclosing function

Duncan Murdoch murdoch@dunc@n @end|ng |rom gm@||@com
Wed Jan 23 16:02:00 CET 2019


On 23/01/2019 5:27 a.m., Jan T Kim wrote:
> Hi Ivan & All,
> 
> R's scoping system basically goes to all environments along the call
> stack when trying to resolve an unbound variable, see the language
> definition [1], section 4.3.4, and perhaps also 2.1.5.

You are misinterpreting that section.  It's not the call stack that is 
searched, it's the chain of environments that starts with the evaluation 
frame of the current function.  Those are very different.  For example,


g <- function() {
   print(secret)
}

f <- function() {
   secret <- "secret"
   g()
}

would fail, because even though secret is defined in the caller of g() 
and is therefore in the call stack, that's irrelevant:  it's not in g's 
evaluation frame (which has no variables) or its parent (which is the 
global environment if those definitions were evaluated there).

Duncan Murdoch

> 
> Generally, unbound variables should be used with care. It's a bit
> difficult to decide whether and how the code should be rewritten,
> I'd say that depends on the underlying intentions / purposes. As it
> is, the code could be simplified to just
> 
>      print("secret");
> 
> but that's probably missing the point.
> 
> Best regards, Jan
> 
> 
> [1] https://cran.r-project.org/doc/manuals/r-release/R-lang.html
> 
> On Wed, Jan 23, 2019 at 12:53:01PM +0300, Ivan Krylov wrote:
>> Hi!
>>
>> I needed to generalize a loss function being optimized inside another
>> function, so I made it a function argument with a default value. It
>> worked without problems, but later I noticed that the inner function,
>> despite being defined in the function arguments, somehow closes over a
>> variable belonging to the outer function, which is defined later.
>>
>> Example:
>>
>> outside <- function(inside = function() print(secret)) {
>> 	secret <- 'secret'
>> 	inside()
>> }
>> outside()
>>
>> I'm used to languages that have both lambdas and variable declaration
>> (like perl5 -Mstrict or C++11), so I was a bit surprised.
>>
>> Does this work because R looks up the variable by name late enough at
>> runtime for the `secret` variable to exist in the parent environment of
>> the `inside` function? Can I rely on it? Is this considered bad style?
>> Should I rewrite it (and how)?
>>
>> -- 
>> Best regards,
>> Ivan
>>
>> ______________________________________________
>> 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.
> 
> ______________________________________________
> 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.
>



More information about the R-help mailing list