[R] Lazy evaluation in function call

Duncan Murdoch murdoch.duncan at gmail.com
Wed May 5 13:28:47 CEST 2010

Thorn wrote:
> Bert Gunter <gunter.berton <at> gene.com> writes:
>> Inline below.
>> -- No.
>> f <- function(x, y = x)x+y  ## lazy evaluation enables this
>>> f(2)
>> [1] 4
>>> f(2,3)
>> [1] 5
> Ok, obviously I was not very precise about what I'd like to do. Sorry. I'm 
> aware of this functionality. But I'd like to use the same idea for existing 
> function. Take biplot as an example. There you have an argument 
> called 'choices' controlling which components you'd like to plot. The standard 
> labels of the axis are the names of the two chosen components, PC1 and PC2 
> say. If one wants to add the explained variance to the axis notation, one 
> could provide the xlab argument:
> biplot(pca-object, xlab=paste("PC1", explained.variance.by.pc1))
> This works out well, and serves it purpose sufficiently. If it happens that 
> you'd like to choose different components, you have to provide the choices 
> argument. As a consequence you have to change your manually adjusted axis 
> notation as well. Hence, I was wondering, if one could do it in a somewhat 
> more automatic fashion:
> biplot(pca-object, xlab=paste("PC", choices[1], explained.varaiance.by(choices
> [1]))
> I've to admit that this is an academic question, because at the time you call 
> biplot, you know which components you want to plot. Thus, you could use the 
> right values for choices and the labs. But I'm interested whether it can be 
> done by telling R that it should evaluate choices[1] not at the prompt level, 
> but at the moment it enters the function biplot, where choices will be known 
> in any case (since it has default values).
> Just to make it clear once again, I'm aware of the possibilities to get this 
> specific task done. But I'm in particular interested, wheter it could be done 
> using R's lazy evaluation mechanism.

I don't know if you can do that.  You'd need something like

f <- function(x, y) x+y

f(x, get("x", environment()))

but it doesn't work.  The problem is you need access to the evaluation 
frame of f, which doesn't exist before you call the function, so you 
need to use lazy evaluation to find it after it has been created.  I 
guessed that environment() would see it, but I was wrong:  that is 
evaluated in the calling environment, so it sees that.

I'm not sure if there's some devious way to do this, but I'd certainly 
recommend against ever using it.  To solve your original problem, just 
make a copy of the function and modify it.

Duncan Murdoch

More information about the R-help mailing list