Strange behavior in which R stores the last variable in a list loop?

When I do a loop to wrap functions in a list, the last function in the input list is always used for all transactions.

wrapper <- function(f)function()f() fs <- list(f = function()"call f", g = function()"call g") ws <- list() for(n in names(fs)) ws[[n]] <- wrapper(fs[[n]]) ws$f() [1] "call g" 

I was expecting "call f" in the above code, but actually it returned "call g" .

Can someone explain to me why this happened?

What is a sign, or in what situation do I have to evaluate to avoid similar

Thank you very much

+5
source share
1 answer

Finally, I understood my own answer

There are two reasons why this happens: the for loop does not have its own environment, and wrapper lazily evaluates its parameter f .

For the first reason: for loop uses the global environment

For the last reason: changing wrapper to function(f){force(f); function()f()} function(f){force(f); function()f()} leads to my expected result in the question.

Detailed explanation:

The cycle in question is interpreted in

 for(n in names(fs)){ tmp <- fs[[n]] ws[[n]] <- wrapper(tmp) } 

Since wrapper lazily evaluates the parameter f , it stores f in its runtime, but does not save its value. Instead, he remembers the method of estimating f when necessary. In other words, it remembers the pair (<environment: R_GlobalEnv>, "tmp") .

Checking the following code clears everything I said.

 tmp <- f wf <- wrapper(tmp) tmp <- g wf() [1] "call g" 

but

 tmp <- f wf <- wrapper(tmp) wf() [1] "call f" tmp <- g wf() [1] "call f" 

The last code printed "call f" in the second call because f is evaluated and stored in the wrapper environment, and there is no need to evaluate again (become g )

+1
source

Source: https://habr.com/ru/post/1274291/


All Articles