哪些R函数不适合于编程使用?

10

一些函数,如 browser ,仅在交互使用时才有意义。

广泛认为 subset 函数应仅在交互式使用中使用.

类似地,sapply 不适合编程使用,因为它不会简化零长度输入的结果。

我正在尝试列出仅适用于交互式使用而不适合编程使用的函数。

计划是创建一个工具来检查软件包,以查看是否调用了这些函数,并发出警告。

还有其他一些函数,如 file.choosereadline, 需要交互性,但对于包含在软件包中是可以接受的,因为最终使用将是交互式的。 对于这种情况,我并不太关心这些函数,但请随意将它们添加到列表中。

我漏掉了哪些函数?


2
在我看来,attach 永远不应该被使用,尤其是在编程中。当然,还有 Viewedit 等实用函数。我不确定我是否同意 sapply 的使用。 - Roland
1
@Roland 同意使用 attach。我对 sapply 的看法是,它会因为零长度输入而导致太多的隐晦错误。例如,sapply(x, length) 返回一个整数向量,除非 x 的长度为 0,否则你会得到一个列表。如果你知道输出的大小是恒定的,则使用 vapply,否则使用 lapply - Richie Cotton
顺便提一下,我提出这个问题的动机是我经常在我的代码中不小心留下对 browser 的调用,如果你将其提交到存储库中,看起来很傻。 - Richie Cotton
sapply是lapply的一个特例。 - rawr
3
这可能有点激进。在编程中使用诸如subset之类的函数时,问题在于它们使用非标准评估其参数。只有当那些使用非标准评估的参数被传递变量时,才存在潜在问题。如果那些受到非标准评估的参数是常量表达式,则仍然可以在函数中安全使用这些函数。例如,在函数中使用subset(data, id == 1)不会有问题。 - G. Grothendieck
显示剩余5条评论
2个回答

8
以下函数应该小心使用(这并不一定意味着它们不适合编程):
- 根据输入的数据不同会输出不同类型结果的函数:`sapply`、`mapply`(默认情况下) - 根据输入长度不同而有不同内部行为的函数:`sample`、`seq` - 在环境中评估某些参数的函数:`$`、`subset`、`with`、`within`、`transform` - 违反正常环境用法的函数:`attach`、`detach`、`assign`、`<<-` - 允许部分匹配的函数:`$` - 仅在交互式使用时有效的函数:`browser`、`recover`、`debug`、`debugonce`、`edit`、`fix`、`menu`、`select.list` - 如果与用户输入一起使用,则可能构成威胁(病毒)的函数:`source`、`eval(parse(text=...))`、`system`
此外,每个生成警告而不是错误的函数在某种程度上都应该引起注意。我建议在编程应用程序中使用 `options(warn = 2)` 将所有警告转换为错误。然后可以通过 `suppressWarnings` 或 `try` 允许特定的警告。

有趣的是,自从R 3.1.0版本以来,对于data.frame列名的部分匹配会发出警告,请参见NEWS - gagolews
……但不包括列表(例如cars$das.list(cars)$d),唉。 - flodel

2

这是回答发帖者评论的内容。该函数输入一个函数并返回其行号及其发现的不良函数。它可能会产生误报,但它们只是警告,因此看起来并不太糟糕。根据需要修改bad即可。

badLines <- function(func) {
    bad <- c("sapply", "subset", "attach")
    regex <- paste0("\\b", bad, "\\b")
    result <- sort(unlist(sapply(regex, FUN = grep, body(func), simplify = FALSE)))
    setNames(result, gsub("\\b", "", names(result), fixed = TRUE))
}
badLines(badLines)

## sapply1  subset  attach sapply2 
##       2       2       2       4 

2
有些人可能会发现 lint 包对这种代码检查很有用。它非常灵活,您可以定义自己的规则。不过它有相对陡峭的学习曲线,并且文档/支持较差。 - flodel
@flodel 关于 lint 包的技巧很不错。我刚刚尝试了 lint(dir("mypackage/R", full.names = TRUE)),它提示了我许多之前没有注意到的问题。 - Richie Cotton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接