[R] Defining functions inside loops

Duncan Murdoch murdoch.duncan at gmail.com
Mon Nov 15 22:38:29 CET 2010


On 15/11/2010 4:10 PM, William Dunlap wrote:
> You could make f[[i]] be function(t)t^2+i for i in 1:10
> with
>       f<- lapply(1:10, function(i)local({ force(i) ; function(x)x^2+i}))
> After that we get the correct results
>      >  f[[7]](100:103)
>      [1] 10007 10208 10411 10616
> but looking at the function doesn't immdiately tell you
> what 'i' is in the function
>      >  f[[7]]
>      function (x)
>      x^2 + i
>      <environment: 0x19d7458>
> You can find it in f[[7]]'s environment
>      >  get("i", envir=environment(f[[7]]))
>      [1] 7
>
> The call to force() in the call to local() is not
> necessary in this case, although it can help in
> other situations.

I thought it would be clearer to use substitute.  My first guess was

  f <- list()
  for (i in 1:10)
    f[[i]] <- substitute(function(t) t^2 + increment, list(increment=i))

but this doesn't work; f[[i]] ends up as an expression evaluating to the 
function we want.   So it looks okay

 > f[[3]]
function(t) t^2 + 3L

but it doesn't work:

 > f[[3]](1)
Error: attempt to apply non-function

So I tried to eval it:

 > eval(f[[3]])
function(t) t^2 + increment

Now that's a puzzle!!  Why did increment come back?  But it works:

 > eval(f[[3]])(1)
[1] 4

(I do actually know the answer to the puzzle, but it took me a while to 
figure out.  Spoiler below.)

So here's what I'd recommend as an answer to the original question:

save <- options(keep.source=FALSE)
f <- list()
for (i in 1:10)
   f[[i]] <- eval(substitute(function(t) t^2 + increment, 
list(increment=i)))
options(save)

Then things look just right:

 > f[[3]]
function (t)
t^2 + 3L
 > f[[3]](4)
[1] 19
 > f[[3]](1)
[1] 4

Of course, I didn't quite meet my objective of coming up with code that 
looked simpler than your lapply() suggestion.  But at least we end up 
with functions with simple environments that print properly.

Duncan Murdoch

>
> Bill Dunlap
> Spotfire, TIBCO Software
> wdunlap tibco.com
>
>> -----Original Message-----
>> From: r-help-bounces at r-project.org
>> [mailto:r-help-bounces at r-project.org] On Behalf Of Eduardo de
>> Oliveira Horta
>> Sent: Monday, November 15, 2010 12:50 PM
>> To: r-help at r-project.org
>> Subject: [R] Defining functions inside loops
>>
>> Hello,
>>
>> I was trying to define a set of functions inside a loop, with
>> the loop index
>> working as a parameter for each function. Below I post a
>> simpler example, as
>> to illustrate what I was intending:
>>
>> f<-list()
>> for (i in 1:10){
>>    f[[i]]<-function(t){
>>      f[[i]]<-t^2+i
>>    }
>> }
>> rm(i)
>>
>> With that, I was expecting that f[[1]] would be a function
>> defined by t^2+1,
>> f[[2]] by t^2+2 and so on. However, the index i somehow
>> doesn't "get in" the
>> function definition on each loop, that is, the functions
>> f[[1]] through
>> f[[10]] are all defined by t^2+i. Thus, if I remove the
>> object i from the
>> workspace, I get an error when evaluating these functions.
>> Otherwise, if
>> don't remove the object i, it ends the loop with value equal
>> to 10 and then
>> f[[1]](t)=f[[2]](t)=...=f[[10]](t)=t^2+10.
>>
>> I am aware that I could simply put
>>
>> f<-function(u,i){
>>    f<-t^2+i
>> }
>>
>> but that's really not what I want.
>>
>> Any help would be appreciated. Thanks in advance,
>>
>> Eduardo Horta
>>
>> 	[[alternative HTML version deleted]]
>>
>> ______________________________________________
>> R-help at r-project.org mailing list
>> 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 at r-project.org mailing list
> 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