开发者

R: How to create a vector of functions?

开发者 https://www.devze.com 2023-04-11 03:23 出处:网络
I would like to create a vector of functions using a two agruments function \'func\', for instance this one:

I would like to create a vector of functions using a two agruments function 'func', for instance this one:

func = function(number, coefficient) {  
    return(coefficient*number)  
}

here is how I create the vector of functions:

vector_of_functions = NULL  
for (i in 1:4) {  
vector_of_functions = c(vector_of_functions,
    function(开发者_如何学Gonumber) func(number=number, coefficient=i))  
}

My issue is that all functions that compose my vector are the same, even if they have been created using different i through the loop. It seams that they are evaluated using the last value of i (which is here a global variable).

Anybody has an idea?

Thanks


You can "attach" the value of i to each function by redefining i in its own local environment (conveniently created by the function, local in R). The resulting function with data "attached" is called a 'closure'.

> vector_of_functions = NULL  
> for (i in 1:4) {  
+ vector_of_functions = c(vector_of_functions,
+     local({i <- i;function(number) func(number=number, coefficient=i)}))
+ }
> vector_of_functions[[1]](1)
[1] 1
> vector_of_functions[[2]](1)
[1] 2
> vector_of_functions[[3]](1)
[1] 3
> vector_of_functions[[4]](1)
[1] 4


This can be solved using an eval-parse construct, although I strongly advice you not to use this construct. It often causes more problems than anything else. But I couldn't get a decent do.call way of doing it.

vector_of_functions = NULL
for (i in 1:4) {
vector_of_functions = c(vector_of_functions,
  eval(parse(text=paste("function(number) func(number=number, coefficient=",i,")"))))
}

Reason is as Aaron explained: everything within the function definition is taken as is until the function evaluation.

Small remark: this is especially a list of functions, and not a vector. It's impossible to have a vector of type "function". It's also absolutely useless, as you have to select the function using the index [[]] before you can use it. Then I'd just add the argument instead of defining a function for every possible value of one of the arguments.

So what you want to achieve is unclear, but if you want to apply func with different coefficients, I wonder why you don't simply do:

> x <- c(10,20,30)
> sapply(1:4,function(y)func(number=x,coefficient=y))
     [,1] [,2] [,3] [,4]
[1,]   10   20   30   40
[2,]   20   40   60   80
[3,]   30   60   90  120

A variation on the theme by Marek (avoiding the parsing):

vector_of_functions = NULL
for (i in 1:4) {
vector_of_functions = c(vector_of_functions,
  eval(substitute(function(number) func(number=number, coefficient=i),list(i=i))))
}

The 1L etc. you get, just indicate they're exact integers (that take less memory space).


The problem is due to lazy evaluation, the 'i' variable is not being evaluted at each step, so when you call the function it uses the last value. The force function was created to force the evaluation in cases like this (there is an example on the help page for ?force that is very similar to your question).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号