curious side effect in R [duplicate] - r

When trying to create a list of similar functions using lapply, I find that all the functions in the list are identical and equal to what the final element should be.
Consider the following:
pow <- function(x,y) x^y
pl <- lapply(1:3,function(y) function(x) pow(x,y))
pl
[[1]]
function (x)
pow(x, y)
<environment: 0x09ccd5f8>
[[2]]
function (x)
pow(x, y)
<environment: 0x09ccd6bc>
[[3]]
function (x)
pow(x, y)
<environment: 0x09ccd780>
When you try to evaluate these functions you get identical results:
pl[[1]](2)
[1] 8
pl[[2]](2)
[1] 8
pl[[3]](2)
[1] 8
What is going on here, and how can I get the result I desire (the correct functions in the list)?

R passes promises, not the values themselves. The promise is forced when it is first evaluated, not when it is passed, and by that time the index has changed if one uses the code in the question. The code can be written as follows to force the promise at the time the outer anonymous function is called and to make it clear to the reader:
pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) } )

This is no longer true as of R 3.2.0!
The corresponding line in the change log reads:
Higher order functions such as the apply functions and Reduce() now
force arguments to the functions they apply in order to eliminate
undesirable interactions between lazy evaluation and variable capture
in closures.
And indeed:
pow <- function(x,y) x^y
pl <- lapply(1:3,function(y) function(x) pow(x,y))
pl[[1]](2)
# [1] 2
pl[[2]](2)
# [1] 4
pl[[3]](2)
# [1] 8

Related

How to maintain list names when concatinating the list with a new variable

In the following example, I would like to add a 3rd variable to a list, which is then used as function arguments in an R function (with do.call). The problem is that I am unable to maintain the names in the concatenated list, thus allowing for the function to call the correct arguments:
# The function (a linear regression)
fun <- function(a=10, b=12, x=1:3){
y <- a + b*x
y
}
# Example of function use
x <- runif(20)
plot(x, fun(x=x))
# New list of function arguments
L <- list(a=3, b=-2, c=4)
x <- runif(20)
# Attempts to call function with arguments
args.incl <- which(names(L) %in% names(formals(fun)))
do.call(fun, args=c(L[args.incl], x=x)) # x is not maintained
do.call(fun, args=list(L[args.incl], x=x)) # a and b names are lost
p.s.
I realize that one solution would be to add x to the list L, but I do not want to do this.
what about
do.call(fun, c(L[args.incl], list(x=x)))
This way you concentrate c the lists L[args.incl] and list(x=x) to list.
> c(L[args.incl], list(x=x))
$a
[1] 3
$b
[1] -2
$x
[1] 0.29227694 0.42304815 0.90256006 0.91309103 0.43949887 0.64453528 0.48544861 0.09220676 0.48814042
[10] 0.47410596 0.32798225 0.18795248 0.17939297 0.88327417 0.45593052 0.29455631 0.06932314 0.10265696
[19] 0.61977174 0.74408227
This does what your p.s. suggests on the fly
This seems to work, using modifyList:
do.call(fun, args=modifyList(L[args.incl], list(x=x)))
# [1] 2.961918 2.071065 2.113825 1.601956 1.931469 2.334662 1.484844 2.943622
# [9] 1.917024 1.838480 1.060532 2.198088 2.451811 2.181310 1.306844 1.397075
# [17] 1.910102 2.940142 2.313939 2.991235
Use this
do.call(fun, args=c(L[args.incl],x=list(x)))

How to make the elements of a matrix callable functions

I want to make a matrix of functions (that I wrote). Then access them element wise and call.
So I have : func1(x) , func2(y), func3(z) and func4(t) that are four R functions I wrote that work fine.They return numerics.
Now if I do:
a_matrix <- matrix(c(a=func1,b=func2,c=func3,d=func4),2,2)
a_func<-a_matrix[1,1]
a_func(x)
I get the following error:
error:attempt to call non-function.
Instead of matrix if I use list,
a_list<-list(a=func1,b=func2,c=func3,d=func4)
a_func<-list$a
a_func(x)
gives expected result
typeof(list$a)
[1] "closure"
If I do :
typeof(a_matrix)
[1] "list"
typeof(a_matrix[1,1])
[1] "list"
(am using R 3.1.1)
When you create non-atomic matrices like that, they are basically made into fancy lists. Similar rules apply to these lists as to regular lists when it comes to indexing; namely that [ ] will always return another list, and [[ ]] will extract the element without the list wrapper. You really want
func1 <- function(x) x+1
func2 <- function(x) x+2
func3 <- function(x) x+3
func4 <- function(x) x+4
a_matrix <- matrix(c(a=func1,b=func2,c=func3,d=func4),2,2)
a_func <- a_matrix[[1,1]]
a_func(5)
# [1] 6
You'd get the same results with your standard list syntax if you did
a_list <- list(a=func1,b=func2,c=func3,d=func4)
a_func <- a_list["a"]
a_func(5)
# Error: could not find function "a_func"
a_func <- a_list[["a"]]
a_func(5)
# [1] 6

How to define a list of (parametric) functions (with local()) [duplicate]

When trying to create a list of similar functions using lapply, I find that all the functions in the list are identical and equal to what the final element should be.
Consider the following:
pow <- function(x,y) x^y
pl <- lapply(1:3,function(y) function(x) pow(x,y))
pl
[[1]]
function (x)
pow(x, y)
<environment: 0x09ccd5f8>
[[2]]
function (x)
pow(x, y)
<environment: 0x09ccd6bc>
[[3]]
function (x)
pow(x, y)
<environment: 0x09ccd780>
When you try to evaluate these functions you get identical results:
pl[[1]](2)
[1] 8
pl[[2]](2)
[1] 8
pl[[3]](2)
[1] 8
What is going on here, and how can I get the result I desire (the correct functions in the list)?
R passes promises, not the values themselves. The promise is forced when it is first evaluated, not when it is passed, and by that time the index has changed if one uses the code in the question. The code can be written as follows to force the promise at the time the outer anonymous function is called and to make it clear to the reader:
pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) } )
This is no longer true as of R 3.2.0!
The corresponding line in the change log reads:
Higher order functions such as the apply functions and Reduce() now
force arguments to the functions they apply in order to eliminate
undesirable interactions between lazy evaluation and variable capture
in closures.
And indeed:
pow <- function(x,y) x^y
pl <- lapply(1:3,function(y) function(x) pow(x,y))
pl[[1]](2)
# [1] 2
pl[[2]](2)
# [1] 4
pl[[3]](2)
# [1] 8

binding a function to a list

Where am I missing something?
FUN<-list()
make.FUN<-function(i) function(n) i+n
for (i in 1:3) FUN[[i]]<-make.FUN(i)
FUN[[1]](1)
If I check FUN assignment I get a reference to a nested function (as expected):
> FUN
[[1]]
function (n)
i + n
<environment: 0x03adfad0>
[[2]]
function (n)
i + n
<environment: 0x03ae0834>
[[3]]
function (n)
i + n
<environment: 0x03ae0604>
>
Problem is that if I check:
> FUN[[1]](1)
[1] 4
>
when I expect 2! (clearly it is overwriting the last value)
On the other hand, if I manually assign for each element of the list:
FUN[[1]]<-make.FUN(1)
FUN[[2]]<-make.FUN(2)
FUN[[3]]<-make.FUN(3)
I get the correct answer:
> FUN[[1]](1)
[1] 2
> FUN[[2]](3)
[1] 5
>
I could workaround using do.call, but I can't realize what the interpreter is assuming in the first loop, or why is do.call mandatory in this case.
When I try:
FUN<-list()
make.FUN<-function(i) function(n) i+n
for (i in 1:3) FUN[[i]]<-do.call('make.FUN',list(i))
I get (as expected):
> FUN[[1]](2)
[1] 3
Any clue? (it only happens when using lists)
Your question is almost a copy-paste of the force example from the doc. You need to do:
FUN <- list()
make.FUN <- function(i) { force(i); function(n) i+n }
for (i in 1:3) FUN[[i]] <- make.FUN(i)
FUN[[1]](1)
# [1] 2
Relevant details from ?force:
force forces the evaluation of a formal argument. This can be useful if the argument will be captured in a closure by the lexical scoping rules and will later be altered by an explicit assignment or an implicit assignment in a loop or an apply function.

Returning anonymous functions from lapply - what is going wrong?

When trying to create a list of similar functions using lapply, I find that all the functions in the list are identical and equal to what the final element should be.
Consider the following:
pow <- function(x,y) x^y
pl <- lapply(1:3,function(y) function(x) pow(x,y))
pl
[[1]]
function (x)
pow(x, y)
<environment: 0x09ccd5f8>
[[2]]
function (x)
pow(x, y)
<environment: 0x09ccd6bc>
[[3]]
function (x)
pow(x, y)
<environment: 0x09ccd780>
When you try to evaluate these functions you get identical results:
pl[[1]](2)
[1] 8
pl[[2]](2)
[1] 8
pl[[3]](2)
[1] 8
What is going on here, and how can I get the result I desire (the correct functions in the list)?
R passes promises, not the values themselves. The promise is forced when it is first evaluated, not when it is passed, and by that time the index has changed if one uses the code in the question. The code can be written as follows to force the promise at the time the outer anonymous function is called and to make it clear to the reader:
pl <- lapply(1:3, function(y) { force(y); function(x) pow(x,y) } )
This is no longer true as of R 3.2.0!
The corresponding line in the change log reads:
Higher order functions such as the apply functions and Reduce() now
force arguments to the functions they apply in order to eliminate
undesirable interactions between lazy evaluation and variable capture
in closures.
And indeed:
pow <- function(x,y) x^y
pl <- lapply(1:3,function(y) function(x) pow(x,y))
pl[[1]](2)
# [1] 2
pl[[2]](2)
# [1] 4
pl[[3]](2)
# [1] 8

Resources