Vou falar rapidamente de um exemplo interessante de como o R avalia os argumentos passados para as funções.

Considere as duas funções abaixo:

foo <- function(){
  cat("foo\n")
  return(1)
}

fooo <- function(x = foo()){
  cat("fooo\n")
  return(x)
}

Ao chamar a função fooo, o que você esperaria que fosse avaliado primeiro? A linha que tem cat("fooo\n") ou a linha que tem cat("foo\n")?

Na minha intuição, a função foo deveria ser avaliada antes, uma vez que ela cria o argumento que será usado em seguida na função fooo. Mas não é isso que acontece.

fooo()
## fooo
## foo
## [1] 1

Agora considere a seguinte pequena alteração no código de fooo.

fooo <- function(x = foo()){
  cat("fooo\n")
  return(1)
}

Agora, ao invés de ela retornar x, ela sempre retornará 1.

Observe agora o resultado da chamada da função fooo.

fooo()
## fooo
## [1] 1

Veja que a função foo nem foi chamada dessa vez, mesmo ela sendo parte necessária do argumento x da função que chamamos.

Isso acontece porque os argumentos das funções são um tipo especial de objeto chamado promise. Um promise captura a expressão necessária para calcular o argumento, mas só o avalia na primeira situação em que o seu valor é necessário.