[Rd] The enclosed environment does not work as expected

Rui Barradas ru|pb@rr@d@@ @end|ng |rom @@po@pt
Sun Apr 3 08:41:47 CEST 2022


Hello,

Another way not to fall into this surprise is to ?force the variable's 
evaluation.


FuncGenerator <- function(value){
   force(value)
   function() message(value)
}

funcSets <- list()
for(i in 1:2)
   funcSets[[i]] <- FuncGenerator(i)

environment(funcSets[[1]])$value
environment(funcSets[[2]])$value


Note that to force evaluation inside the returned function doesn't work. 
The function will get a copy of value and evaluate the copy, not what 
the function factory is getting. I too find lazy evaluation confusing 
and the best/only way is to try it out and eventualy get it right.


# wrong
FuncGenerator <- function(value){
   function(value) {
     force(value)
     message(value)
   }
}



Hope this helps,

Rui Barradas

Às 05:52 de 03/04/2022, Jiefei Wang escreveu:
> Hi Eric,
> 
> Wow, Thanks for the explanation. Even though I know the lazy
> evaluation, I never thought it can have this surprising effect. Good
> to know it now.
> 
> Best,
> Jiefei
> 
> On Sun, Apr 3, 2022 at 12:20 AM Eric Berger <ericjberger using gmail.com> wrote:
>>
>> Hi Jiefei,
>> This is related to "lazy evaluation". Alternatives for dealing with it are discussed here:
>>
>> https://stackoverflow.com/questions/29084193/how-to-not-fall-into-rs-lazy-evaluation-trap
>>
>> HTH,
>> Eric
>>
>>
>> On Sun, Apr 3, 2022 at 6:32 AM Jiefei Wang <szwjf08 using gmail.com> wrote:
>>>
>>> Hi,
>>>
>>> It seems like the enclosed environment does not work well with the
>>> loop. Here is a simple example
>>> ```
>>> FuncGenerator <- function(value){
>>>      function() message(value)
>>> }
>>>
>>> funcSets <- list()
>>> for(i in 1:2)
>>>      funcSets[[i]] <- FuncGenerator(i)
>>>
>>> environment(funcSets[[1]])$value
>>> # [1] 2
>>> environment(funcSets[[2]])$value
>>> # [1] 2
>>> ```
>>> The output from the last two lines is simply 2. I expect the first
>>> should be 1 and the second is 2. However, if I ask R to execute the
>>> message function before accessing its environment, the result is
>>> correct again.
>>>
>>> ```
>>> FuncGenerator <- function(value){
>>>      function() message(value)
>>> }
>>>
>>> funcSets <- list()
>>> for(i in 1:2)
>>>      funcSets[[i]] <- FuncGenerator(i)
>>>
>>> ## Ask to evaluate the function
>>> for(i in 1:2){
>>>      funcSets[[i]]()
>>> }
>>> # 1
>>> # 2
>>> environment(funcSets[[1]])$value
>>> # [1] 1
>>> environment(funcSets[[2]])$value
>>> # [1] 2
>>> ```
>>> This does not make any sense to me since the function simply prints
>>> out its variable `value`. It should not change the value of the
>>> variable, so I think this might be a bug in the code optimizer. This
>>> issue can only be corrected by the loop(like the second example),
>>> manually evaluating the function without the loop will give you the
>>> same result as the first example.
>>>
>>> Here is my session information
>>>> sessionInfo()
>>> R version 4.1.2 (2021-11-01)
>>> Platform: x86_64-w64-mingw32/x64 (64-bit)
>>> Running under: Windows 10 x64 (build 19044)
>>>
>>>
>>> Best,
>>> Jiefei
>>>
>>> ______________________________________________
>>> R-devel using r-project.org mailing list
>>> https://stat.ethz.ch/mailman/listinfo/r-devel
> 
> ______________________________________________
> R-devel using r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel



More information about the R-devel mailing list