brentonk
brentonk

Reputation: 1308

Lazy evaluation of supplied arguments

Say I have the following function:

foo <- function(x, y = min(m)) {
    m <- 1:10
    x + y
}

When I run foo(1), the returned value is 2, as expected. However, I cannot run foo(1, y = max(m)) and receive 11, since lazy evaluation only works for default arguments. How can I supply an argument but have it evaluate lazily?

Upvotes: 7

Views: 793

Answers (3)

shadow
shadow

Reputation: 22293

You can use a substitute, eval combintation.

foo <- function(x, y = min(m)) {
  y <- substitute(y)
  m <- 1:10
  x + eval(y)
}

foo(1)
## [1] 2
foo(1, y = max(m))
## [1] 11

Upvotes: 0

Andrew Redd
Andrew Redd

Reputation: 4692

The simple answer is that you can't and shouldn't try to. That breaks scope and could wreak havoc if it were allowed. There are a few options that you can think about the problem differently.

first pass y as a function

foo<-function(x,y=min){
m<-1:10
x+y(m)
}

if a simple function does not work you can move m to an argument with a default.

foo<-function(x,y=min(m),m=1:10){
x+y(m)
}

Since this is a toy example I would assume that this would be too trivial. If you insist on breaking scope then you can pass it as an expression that is evaluated explicitly.

foo<-function(x,y=expression(min(m))){
m<-1:10
x+eval(y)
}

Then there is the option of returning a function from another function. And that might work for you as well, depending on your purpose.

bar<-function(f)function(x,y=f(m)){
m<-1:10
x+y
}
foo.min<-bar(min)
foo.min(1)  #2
foo.max<-bar(max)
foo.max(1)  #10

But now we are starting to get into the ridiculous.

Upvotes: 6

brentonk
brentonk

Reputation: 1308

My solution was to just change the default argument:

R> formals(foo)$y <- call("max", as.name("m"))
R> foo(1)
[1] 11

Upvotes: 1

Related Questions