I have a function which does extra things if a non-empty value is supplied to what otherwise would be an optional parameter. If the argument is not supplied, the function doesn't do anything extra.
Is it better to use NA
or NULL
? What are the advantages of either?
For example, if I use NA
, then I can quickly check which arguments were not supplied by using: is.na(as.list(environment()))
in the function body, which does not work with is.null
.
Here is an example of why I want to use NA
I am trying to build an R connector to the Geckoboard bar chart API. It has many optional arguments. If I do the following, it is very easy to use the package jsonlite
to supply the optional arguments.
get_barchart_json <- function(data, x_axis = list(labels = NA, type = NA), y_axis = list(format = NULL, unit = NULL)){
payload <- "{"
textappend(payload) <- '"series": [{"data":['
textappend(payload) <- paste0(data, collapse = ",")
textappend(payload) <- ']}]'
if(any(!is.na(x_axis))){
textappend(payload) <- ","
textappend(payload) <- jsonlite::toJSON(x_axis, auto_unbox = TRUE)
}
if(any(!is.na(y_axis))){
textappend(payload) <- ","
textappend(payload) <- jsonlite::toJSON(y_axis, auto_unbox = TRUE)
}
# finish construction
textappend(payload) <- '}'
return(payload)
}
which returns, for example:
cat(get_barchart_json(data = c(1,2,3,4), x_axis = list(labels = c("a", "b", "c", "d"), format = "text"), y_axis = list(format = 'decimal')))
NB: textappend
is:
`textappend<-` <- function(payload, value){
payload <- paste0(payload, value)
payload
}
For an /optional/ value, use NULL. I feel it's kind of an anti-pattern to allow missing argument values - it's hard to know which values you are leaving out. With NULL, the 3rd argument is always the 3rd argument, etc...
If the argument is not supplied, the function doesn't do anything extra. Is it better to use NA or NULL? What are the advantages of either? For example, if I use NA, then I can quickly check which arguments were not supplied by using: is.na (as.list (environment ())) in the function body, which does not work with is.null.
The integers 0 and 1 are common default values to use when a parameter’s value needs to be an integer. This is because 0 and 1 are often useful fallback values to have.
Therefore, you can use the variable directly within an if statement to check whether an optional argument was used. Another common value that’s often used as a default value is None. This is Python’s way of representing nothing, although it is actually an object that represents the null value.
NA is for data values which are missing from data sets. It will also propagate in places that NULL will not, as it can be type-coerced. For an /optional/ value, use NULL.
I feel it's kind of an anti-pattern to allow missing argument values - it's hard to know which values you are leaving out. With NULL, the 3rd argument is always the 3rd argument, etc...
See NA vs. NULL.
You actually have 3 options: NA
, NULL
, or no default. Under most circumstances, NULL
is the best option.
function(x, optional_arg = NULL)
{
if(is.null(optional_arg))
{
# do something
}
# rest of body code
}
This doesn't work if you want users to be able do pass NULL
as a legitimate value to optional_arg
. In that case, use
function(x, optional_arg)
{
if(missing(optional_arg))
{
# do something
}
# rest of body code
}
A default of NA
is only useful for cases where the optional arg should take one of three values, and it makes more sense to store it as a logical value rather than a string.
function(x, optional_arg = NA)
{
if(is.na(optional_arg))
{
# do something
} else if(optional_arg)
{
# do something else
} else # case of optional_arg == FALSE
{
# do a third thing
}
# rest of body code
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With