"Correct" way to specifiy optional arguments in R functions

You could also use missing() to test whether or not the argument y was supplied:

fooBar <- function(x,y){
    if(missing(y)) {
        x
    } else {
        x + y
    }
}

fooBar(3,1.5)
# [1] 4.5
fooBar(3)
# [1] 3

To be honest I like the OP's first way of actually starting it with a NULL value and then checking it with is.null (primarily because it is very simply and easy to understand). It maybe depends on the way people are used to coding but the Hadley seems to support the is.null way too:

From Hadley's book "Advanced-R" Chapter 6, Functions, p.84 (for the online version check here):

You can determine if an argument was supplied or not with the missing() function.

i <- function(a, b) {
  c(missing(a), missing(b))
}
i()
#> [1] TRUE TRUE
i(a = 1)
#> [1] FALSE  TRUE
i(b = 2)
#> [1]  TRUE FALSE
i(1, 2)
#> [1] FALSE FALSE

Sometimes you want to add a non-trivial default value, which might take several lines of code to compute. Instead of inserting that code in the function definition, you could use missing() to conditionally compute it if needed. However, this makes it hard to know which arguments are required and which are optional without carefully reading the documentation. Instead, I usually set the default value to NULL and use is.null() to check if the argument was supplied.