81

I have a function f that takes two parameters (p1 and p2):

If for the parameter p2 no value was passed to the function, the value of p1^2 should be used instead. But how can I find out within the function, if a value is given or not. The problem is that the variable p2 is not initialized if there was no value. Thus I can't test for p2 being NULL.

f <- function(p1, p2) {
    if(is.null(p2)) {
        p2=p1^2
    }
    p1-p2
}

Is it somehow possible to check if a value for p2 was passed to the function or not? (I could not find an isset() - function or similar things.)

joran
  • 169,992
  • 32
  • 429
  • 468
R_User
  • 10,682
  • 25
  • 79
  • 120

3 Answers3

107

You use the function missing() for that.

f <- function(p1, p2) {
    if(missing(p2)) {
        p2=p1^2
    }
    p1-p2
}

Alternatively, you can set the value of p2 to NULL by default. I sometimes prefer that solution, as it allows for passing arguments to nested functions.

f <- function(p1, p2=NULL) {
    if(is.null(p2)) {
        p2=p1^2
    }
    p1-p2
}

f.wrapper <-function(p1,p2=NULL){
    p1 <- 2*p1
    f(p1,p2)
}
> f.wrapper(1)
[1] -2
> f.wrapper(1,3)
[1] -1

EDIT: you could do this technically with missing() as well, but then you would have to include a missing() statement in f.wrapper as well.

Joris Meys
  • 106,551
  • 31
  • 221
  • 263
  • 2
    +1 for the `NULL` default alternative. Re: the EDIT you added, how would you pass `missing`'ness down through the wrapper function? – Josh O'Brien Nov 01 '11 at 13:56
  • @JoshO'Brien Passing `missing`-ness on is complicated AFAIK - but possible. That's why `NULL` is so much easier in this case. – Tommy Nov 01 '11 at 16:48
  • ... So a separate question might be warranted for passing `missing`-ness on. – Tommy Nov 01 '11 at 16:57
  • 1
    @JoshO'Brien That would have to be `if(missing(p2)) f(p1) else f(p1,p2)`. Or you could pass the arguments using the dots argument. – Joris Meys Nov 01 '11 at 19:13
  • Thanks. FWIW, I can't see how to do this with dots, if both functions have formal args `p1` and `p2`. Another alternative uses the following in the body of `f.wrapper()`: `{cl <- match.call(); cl$p1 <- 2*p1; cl[[1]] <- f; eval(cl)}`. All this goes to show just how much cleaner your `NULL` alternative really is! – Josh O'Brien Nov 01 '11 at 20:23
  • @JoshO'Brien : you only give `f` the formal args `p1` and `p2`. `f.wrapper <- function(p1, ...){ blabla f(p1, ...)}`. That would work and is how it's often done in R itself – Joris Meys Nov 01 '11 at 20:26
8

In a case like this you can also use something like this:

f <- function(p1, p2 = p1 ^ 2) {
    p1-p2
}

See the part on Lazy evaluation at http://adv-r.had.co.nz/Functions.html

Johan
  • 810
  • 6
  • 12
  • I usually write it like this, so when would `missing` be most appropriate? – Diego Aug 24 '21 at 23:53
  • @Diego, if you look at the ?missing documentation you'll find an example that would be difficult to implement using this technique. – Johan Feb 21 '22 at 21:24
8

I think '?missing' should do it.

mdsumner
  • 29,099
  • 6
  • 83
  • 91