To date when writing R functions I've passed undefined arguments as NULL values and then tested whether they are NULL i.e.
f1 <- function (x = NULL) {
if(is.null(x))
...
}
However I recently discovered the possibility of passing undefined arguments as missing i.e.
f2 <- function (x) {
if(missing(x))
...
}
The R documentation states that
Currently missing can only be used in the immediate body of the function that defines the argument, not in the body of a nested function or a local call. This may change in the future.
Clearly this is one disadvantage of using missing to determine undefined values are there any others people or aware of? Or to phrase the question in a more useful form "When do you use missing versus NULL values for passing undefined function arguments in R and why?"
NULL
is just another value you can assign to a variable. It's no different than any other default value you'd assign in your function's declaration.missing
on the other hand checks if the user supplied that argument, which you can do before the default assignment - which thanks to R's lazy evaluation only happens when that variable is used.A couple of examples of what you can achieve with this are: arguments with no default value that you can still omit - e.g.
file
andtext
inread.table
, or arguments with default values where you can only specify one - e.g.n
andnmax
inscan
.You'll find many other use cases by browsing through R code.
missing(x)
seems to be a bit faster than using default arg tox
equal toNULL
.Note that in the
f1
casex
is still reported as missing if you make a callf1()
, but it has a value that may be read withinf1
.The second case is more general than the first one.
missing()
just means that the user did not pass any value.is.null()
(withNULL
default arg) states that the user either did not pass anything or he/she passedNULL
.By the way,
plot.default()
andchisq.test()
useNULL
for their second arguments. On the other hand,getS3method('t.test', 'default')
usesNULL
fory
argument andmissing()
formu
(in order to be prepared for many usage scenarios).I think that some R users will prefer
f1
-type functions, especially when working with the*apply
family:Achieving that in the
f2
case is not so straightforward.