R 我应该使用NULL或NA作为可选函数参数的默认值吗

R 我应该使用NULL或NA作为可选函数参数的默认值吗,r,function,R,Function,我有一个函数,如果为一个可选参数提供了一个非空值,它会做额外的事情。如果未提供参数,则函数不会执行任何额外操作 使用NA还是NULL更好?两者的优点是什么 例如,如果我使用NA,那么我可以通过在函数体中使用:is.NA(as.list(environment()),快速检查没有提供哪些参数,该函数体不使用is.null 下面是一个示例,说明我为什么要使用NA 我正在尝试建立一个R连接器到。它有许多可选参数。如果我执行以下操作,那么使用包jsonlite提供可选参数是非常容易的 get_barch

我有一个函数,如果为一个可选参数提供了一个非空值,它会做额外的事情。如果未提供参数,则函数不会执行任何额外操作

使用
NA
还是
NULL
更好?两者的优点是什么

例如,如果我使用
NA
,那么我可以通过在函数体中使用:
is.NA(as.list(environment())
,快速检查没有提供哪些参数,该函数体不使用
is.null

下面是一个示例,说明我为什么要使用
NA

我正在尝试建立一个R连接器到。它有许多可选参数。如果我执行以下操作,那么使用包
jsonlite
提供可选参数是非常容易的

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)

}
注意:
textappen
是:

`textappend<-` <- function(payload, value){
 payload <- paste0(payload, value)    
 payload
}

`textpappendNA用于数据集中缺少的数据值。它还将在NULL不会传播的地方传播,因为它可以被类型强制。对于/可选/值,请使用NULL


我觉得允许遗漏参数值是一种反模式——很难知道遗漏了哪些值。如果为NULL,则第三个参数始终是第三个参数,以此类推


您实际上有3个选项:
NA
NULL
,或者没有默认值。在大多数情况下,
NULL
是最佳选择

function(x, optional_arg = NULL)
{
  if(is.null(optional_arg))
  {
    # do something
  }
  # rest of body code
}
如果您希望用户能够将
NULL
作为合法值传递给
可选参数,则此操作无效。在这种情况下,使用

function(x, optional_arg)
{
  if(missing(optional_arg))
  {
    # do something
  }
  # rest of body code
}
默认值
NA
仅适用于可选参数应采用三个值之一的情况,并且将其存储为逻辑值而不是字符串更有意义

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
}

正如Hansi在评论中提到的那样,依赖missing对于交互使用来说是很好的,但是对于使用嵌套函数(将参数传递给down)的编程使用来说是很烦人的。考虑下面的最小例子。

假设我们有一个函数,当缺少
arg2
时,它会执行一些特殊的操作。我们使用标准的
missing
方法进行检查

> func1 = function(arg1, arg2) {
  if (missing(arg2)) print("no arg2")
  print(arg1)
  }
> func1("abc")
[1] "no arg2"
[1] "abc"
这个很好用。但是,如果我们从另一个传递参数并具有默认值的函数调用它,会怎么样

> func2 = function(arg1, arg2 = "def") {
  func1(arg1 = arg1, arg2 = arg2)
  }
> func2("abc")
[1] "abc"
> func2("abc", arg2 = )
[1] "abc"
> func2("abc", arg2 = NULL)
[1] "abc"
> func2("abc", arg2 = NA)
[1] "abc"
arg2
丢失时,我们似乎无法触发特殊功能,因为要将
arg2
设置为从另一个从未丢失参数的函数中丢失并不容易


.

我不明白您所说的“允许缺少参数值”是什么意思。实际上,这并不是完全重复的,但我所说的内容已经写在这里:谢谢,非常有用的链接。因此,从规范的角度来看,似乎应该使用
NULL
,然而,使用
NA
也有其优点。似乎在“偏好”的范围内,但现在你有了我的意见,哪一个更干净。=)“很难知道遗漏了哪些值”:这就是为什么函数调用中的命名参数是一件好事!“缺少”开始成为一个麻烦,当您使用嵌套很深的函数,并且希望在更高级别上控制某些元素时,将其设置为NULL要比编写代码根据提供的更高级别的参数对较低级别的函数进行多次调用容易得多。@Hansi。是的。就像我说的,
NULL
通常是最好的选择。
> func2 = function(arg1, arg2 = "def") {
  func1(arg1 = arg1, arg2 = arg2)
  }
> func2("abc")
[1] "abc"
> func2("abc", arg2 = )
[1] "abc"
> func2("abc", arg2 = NULL)
[1] "abc"
> func2("abc", arg2 = NA)
[1] "abc"