30

R 允许通过<-和进行赋值=

尽管两个赋值运算符之间存在细微差别,但似乎有一个广泛的共识,即<-=, as也更好,因为=它也用作将值映射到参数的运算符,因此它的使用可能会导致模棱两可的陈述。下面举例说明了这一点:

> system.time(x <- rnorm(10))
   user  system elapsed 
      0       0       0 
> system.time(x = rnorm(10))
Error in system.time(x = rnorm(10)) : unused argument(s) (x = rnorm(10))

事实上,Google 风格的代码不允许使用=for assignment(请参阅对此答案的评论以获取相反的观点)。

我也几乎专门<-用作赋值运算符。但是,上一句中的差不多就是这个问题的原因。在=我的代码中充当赋值运算符时,它总是偶然的,如果它导致问题,通常很难发现。

我想知道是否有办法通过关闭分配并让 R 在任何时候用于分配=时抛出错误。=

最佳情况下,这种行为只会发生在全局环境中的代码上,因为在附加的命名空间中很可能有代码=用于分配并且不应该中断。

(这个问题的灵感来自与Jonathan Nelson的讨论)

4

4 回答 4

37

这是一个候选人:

`=` <- function(...) stop("Assignment by = disabled, use <- instead")
# seems to work
a = 1
Error in a = 1 : Assignment by = disabled, use <- instead
# appears not to break named arguments
sum(1:2,na.rm=TRUE)
[1] 3
于 2012-09-13T23:40:03.600 回答
9

我不确定,但也许简单地覆盖的分配=对你来说就足够了。毕竟,`=`是一个和其他名字一样的名字——几乎。

> `=` <- function() { }
> a = 3
Error in a = 3 : unused argument(s) (a, 3)
> a <- 3
> data.frame(a = 3)
  a
1 3

因此,任何使用=for 赋值都会导致错误,而使用它来命名参数仍然有效。除非实际执行了相关行,否则它在函数中的使用可能会被忽视。

于 2012-09-13T23:40:15.687 回答
7

lint(CRAN) 有一个样式检查,所以假设你的代码在一个文件中,你可以对它运行 lint,它会警告你那些带有=分配的行号。

这是一个基本示例:

temp <- tempfile()
write("foo = function(...) {
          good <- 0
          bad = 1
          sum(..., na.rm = TRUE)
       }", file = temp)

library(lint) 
lint(file = temp, style = list(styles.assignment.noeq))
# Lint checking: C:\Users\flodel\AppData\Local\Temp\RtmpwF3pZ6\file19ac3b66b81
# Lint: Equal sign assignemnts: found on lines 1, 3

lint软件包附带了一些您可能会感兴趣的测试,包括:

  • 警告不要正确分配
  • 推荐周围的空间=
  • 推荐逗号后的空格
  • 建议中缀之间有空格(又称二元运算符)
  • 警告标签
  • 警告最大线宽的可能性
  • 警告函数调用内部的赋值

您可以打开或关闭任何预定义的样式检查,也可以编写自己的。然而,该软件包仍处于起步阶段:它带有一些错误(https://github.com/halpo/lint)并且文档有点难以消化。作者反应灵敏,并慢慢做出改进。

于 2012-09-14T03:56:39.747 回答
3

如果您不想破坏现有代码,那么这样的事情(打印警告而不是错误)可能会起作用 - 您给出警告然后分配给parent.frame使用<-(以避免任何递归)

`=` <- function(...){
        .what <- as.list(match.call())
        .call <-  sprintf('%s <- %s', deparse(.what[[2]]),  deparse(.what[[3]]))
        mess <- 'Use <- instead of = for assigment '
        if(getOption('warn_assign', default = T)) {
        stop (mess) } else {
        warning(mess)
        eval(parse(text =.call), envir = parent.frame())  
          }
        }

如果您设置options(warn_assign = F)=则将警告并分配。其他任何事情都会引发错误并且不会分配。

使用示例

# with no option set
z = 1
## Error in z = 1 : Use <- instead of = for assigment 
options(warn_assign = T)
z = 1
## Error in z = 1 : Use <- instead of = for assigment 
 options(warn_assign = F)
 z = 1
## Warning message:
##  In z = 1 : Use <- instead of = for assigment 

更好的选择

我认为formatRorlint和代码格式化是更好的方法。

于 2012-09-14T05:43:44.060 回答