在R中,具有与基本R函数同名的variables的问题到底是什么?

似乎通常认为使用具有相同名称的基数R中的函数的variables名称是不好的编程习惯。

例如,写下以下内容很诱人:

data <- data.frame(...) df <- data.frame(...) 

现在,函数data加载数据集,而函数df计算f密度函数。

同样,写这样的文章是很有诱惑力的:

 a <- 1 b <- 2 c <- 3 

这被认为是不好的forms,因为函数c将结合它的论点。

但是:在R函数lm ,为了计算线性模型, data被用作参数。 换句话说, datalm函数中变成一个显式variables。

所以:如果R核心团队可以为variables和函数使用相同的名称,那么我们是不是凡人呢?

答案不是R会混淆。 尝试下面的例子,我明确地分配一个名字为c的variables。 R不会因为variables和函数之间的差异而感到困惑:

 c("A", "B") [1] "A" "B" c <- c("Some text", "Second", "Third") c(1, 3, 5) [1] 1 3 5 c[3] [1] "Third" 

问题:具有与基本R函数同名的variables的问题究竟是什么?

真的没有一个。 在寻找函数时,R通常不会search对象(非函数对象):

 > mean(1:10) [1] 5.5 > mean <- 1 > mean(1:10) [1] 5.5 > rm(mean) > mean(1:10) [1] 5.5 

@Joris和@Sacha所示的例子是糟糕的编码让你失望。 一个更好的书写foo是:

 foo <- function(x, fun) { fun <- match.fun(fun) fun(x) } 

当使用时给出:

 > foo(1:10, mean) [1] 5.5 > mean <- 1 > foo(1:10, mean) [1] 5.5 

在某些情况下,这会把你赶出去,而na.omit的例子是na.omit ,因为lm()使用了标准的非标准评估,所以IIRC正在发生。

几个答案还将TTRUE问题与function问题的掩饰混为一谈。 由于TTRUE不是@ Andrie问题范围之外的函数。

问题不在于计算机,而在于用户。 一般来说,代码可能变得很难debugging。 input错误很容易,所以如果你这样做:

 c <- c("Some text", "Second", "Third") c[3] c(3) 

你得到正确的结果。 但是如果你错过了代码中的某处并键入c(3)而不是c[3] ,那么发现错误并不会那么容易。

范围界定也会导致非常混乱的错误报告。 采取以下有缺陷的function:

 my.foo <- function(x){ if(x) c <- 1 c + 1 } > my.foo(TRUE) [1] 2 > my.foo(FALSE) Error in c + 1 : non-numeric argument to binary operator 

用更复杂的function,这可能导致你在一个无处不在的debugging线索。 如果在上面的函数中用creplacec ,那么错误将会被读为“ object 'x' not found ”。 这将导致更快的编码错误。

接下来,它会导致相当混乱的代码。 像c(c+c(a,b,c))的代码比c(d+c(a,b,d))要求大脑更多。 再次,这是一个微不足道的例子,但它可以有所作为。

显然,你也可以得到错误。 当你期望一个function,你不会得到它,这可能会导致另一个恼人的错误:

 my.foo <- function(x,fun) fun(x) my.foo(1,sum) [1] 1 my.foo(1,c) Error in my.foo(1, c) : could not find function "fun" 

一个更现实(和现实生活)的例子,这可能会导致麻烦:

 x <- c(1:10,NA) y <- c(NA,1:10) lm(x~y,na.action=na.omit) # ... correct output ... na.omit <- TRUE lm(x~y,na.action=na.omit) Error in model.frame.default(formula = x ~ y, na.action = na.omit, drop.unused.levels = TRUE) : attempt to apply non-function 

如果na.omit <- TRUE在您的代码中出现50行,请尝试找出这里有什么问题…

在@Andrie的评论之后回答编辑,以包含混淆错误报告的例子

R对此非常强大,但你可以想办法打破它。 例如,考虑这个function:

 foo <- function(x,fun) fun(x) 

这简单地适用于x fun 。 不是最好的方式做到这一点,但你可能会遇到这个从某人的脚本左右。 这适用于mean()

 > foo(1:10,mean) [1] 5.5 

但是,如果我分配一个新的价值意味着它打破:

 mean <- 1 foo(1:10,mean) Error in foo(1:10, mean) : could not find function "fun" 

这很less发生,但可能会发生。 如果同样的事情意味着两件事情,这也是令人困惑的:

 mean(mean) 

既然使用任何你想要的名字是微不足道的,为什么不使用一个不同的名字,然后基地的Rfunction? 而且,对于一些Rvariables,这变得更加重要。 想想重新分配'+'function! 另一个很好的例子是TF重新分配,可以打破这么多的脚本。

我认为问题在于人们在全球环境中使用这些function,并且由于某些您不应该得到的意想不到的错误而导致挫败感。 想象一下,你只是运行了一个可重复的例子(可能相当长),覆盖了你在仿真中使用的一个函数,需要很长时间才能到达你想要的地方,然后突然间出现一个有趣的错误。 在closures的环境中使用已经存在的variables函数名称(如函数)在函数closures后被删除,不应该造成伤害。 假设程序员知道这种行为的所有后果。

答案很简单。 那么,那种。

底线是你应该避免混淆。 从技术上讲,没有理由给你的variables专有名称,但它使你的代码更容易阅读。

假设有一行代码包含data()[1]或类似的代码(这一行可能没有意义,但这只是一个例子):虽然现在你很清楚你正在使用函数数据,一个读者注意到那里有一个data.frame命名的数据,可能会感到困惑。

如果你不是不偏不倚,记住,读者可能在半年左右,试图弄清楚你正在用“旧代码”做什么。

从一个学会使用长variables名称和命名约定的人那里得到它:回报!

我同意@Gavin Simpson和@Nick Sabbe认为没有问题,但这更多的是代码的可读性问题。 因此,生活中的许多事情,这是一个约定和共识的问题。

我认为给出一般build议是一个很好的习惯:不要将你的variables命名为基本的R函数!

这个build议和其他好的build议一样。 例如大家都知道我们不要喝太多的酒,不要吃太多的不健康的食物,但是我们不时会遵循这些build议,在吃太多垃圾食物的时候喝醉了。

这个build议也是一样的。 命名数据参数data显然是有意义的。 但是,命名数据向量的mean就不那么有意义了。 虽然可能有这样的情况,即使这似乎是适当的。 但要尽量避免这些情况的清晰。

虽然有些语言可能会允许,但是IF IF THEN THEN ELSE ELSE人想到其他的话。 总的来说,这被认为是很差的做法。 这并不是说我们不想让你有机会炫耀你对语言的高级知识,总有一天,我们将不得不处理那些代码,而我们只是凡人而已。

因此,如果你感觉到额外的温暖和模糊,那么保存你的编程技巧就不要打破每晚的构build,并给你的variables合理的名字,一致的shell。