在R中赋值运算符=和<-之间有什么区别?

我知道操作符略有不同,如本例所示

x <- y <- 5
x = y = 5
x = y <- 5
x <- y = 5
# Error in (x <- y) = 5 : could not find function "<-<-"

但这是唯一的不同吗?


当前回答

谷歌的R样式指南通过禁止赋值使用“=”简化了这个问题。不错的选择。

https://google.github.io/styleguide/Rguide.xml

R手册详细介绍了所有5个赋值操作符。

http://stat.ethz.ch/R-manual/R-patched/library/base/html/assignOps.html

其他回答

在R中赋值运算符=和<-之间有什么区别?

如示例所示,=和<-的运算符优先级略有不同(当它们混合在同一个表达式中时,运算符优先级决定了求值的顺序)。事实上,R中的?语法给出了以下操作符优先级表,从高到低:

... ' -> ->> '向右分配 ' <- <<- '赋值(从右向左) ' = '赋值(从右到左) ...

但这是唯一的不同吗?

既然你问的是赋值操作符:是的,这是唯一的区别。然而,如果你不这么认为,也情有可原。甚至?assignOps的R文档也声称有更多的区别:

操作符<-可以在任何地方使用, 而运算符=只允许在顶层(例如, 在命令提示符处输入的完整表达式中)或作为一个 一个带括号的表达式列表中的子表达式。

让我们不要过分强调它:R文档是错误的。这很容易显示:我们只需要找到一个=运算符的反例,它既不是(a)在顶层,也不是(b)在一个带括号的表达式列表中的子表达式(例如{…;})。-闲话不多说:

x
# Error: object 'x' not found
sum((x = 1), 2)
# [1] 3
x
# [1] 1

显然,我们已经在上下文(a)和(b)之外执行了赋值,使用=。那么,为什么R语言核心特性的文档几十年来一直是错误的呢?

这是因为在R的语法中,符号=有两个不同的含义,经常被混为一谈(甚至是专家,包括在上面引用的文档中):

第一个含义是赋值操作符。这是我们目前为止讨论的全部内容。 第二个含义不是一个操作符,而是一个语法标记,表示在函数调用中传递的命名参数。与=运算符不同,它在运行时不执行任何操作,它只是改变表达式的解析方式。

那么R如何决定=的给定用法是指操作符还是指定参数传递?让我们来看看。

在任何一段一般形式的代码中…

‹function_name›(‹argname› = ‹value›, …)
‹function_name›(‹args›, ‹argname› = ‹value›, …)

…the =是定义命名参数传递的令牌:它不是赋值操作符。此外,=在某些句法环境中是完全禁止的:

if (‹var› = ‹value›) …
while (‹var› = ‹value›) …
for (‹var› = ‹value› in ‹value2›) …
for (‹var1› in ‹var2› = ‹value›) …

任何这些都会引发错误“unexpected”=“in”。

在任何其他上下文中,=指赋值操作符调用。特别是,只要在子表达式周围加上括号,就可以使上面的(a)有效,(b)为赋值。例如,下面执行赋值:

median((x = 1 : 10))

但也:

if (! (nf = length(from))) return()

现在您可能会反对说这样的代码很糟糕(您可能是对的)。但是我从base::文件中获取了这段代码。复制函数(用=替换<-)——这是R核心代码库中普遍存在的模式。

约翰·钱伯斯(John Chambers)最初的解释,也就是R文档可能基于的解释,实际上正确地解释了这一点:

[=赋值]只允许出现在语法中的两个地方:在顶层(作为一个完整的程序或用户类型的表达式);当与周围的逻辑结构隔离时,通过大括号或额外的一对括号。


总的来说,默认情况下,操作符<-和=做同样的事情。但它们中的任何一个都可以被单独覆盖以改变其行为。相比之下,<-和->(从左到右赋值)虽然语法不同,但总是调用相同的函数。覆盖一个也会覆盖另一个。知道这一点很少是实际的,但它可以用于一些有趣的恶作剧。

根据John Chambers的说法,操作符=只允许在“顶层”,这意味着它不允许在像if这样的控制结构中,这使得下面的编程错误是非法的。

> if(x = 0) 1 else x
Error: syntax error

正如他所写的,“在控制表达式中禁止新的赋值形式[=]可以避免编程错误(如上面的例子),与其他S赋值相比,相等操作符更有可能出现这种错误。”

如果它“通过大括号或一对额外的圆括号与周围的逻辑结构隔离”,则可以做到这一点,因此if ((x = 0)) 1否则x就可以工作。

参见http://developer.r-project.org/equalAssign.html

来自官方R文档:

操作符<-和=赋值到它们所处的环境 进行了评估。操作符<-可以在任何地方使用,而 操作符=只允许在顶层(例如,在 在命令提示符处键入的完整表达式)或作为 带括号的表达式列表中的子表达式。

我不确定Patrick Burns的书R inferno是否在8.2.26中被引用,其中=不是<的同义词- Patrick说“当你想设置一个函数的参数时,你显然不想使用'<-'。”这本书可以在https://www.burns-stat.com/documents/books/the-r-inferno/上买到

这也有助于理解这两个操作符之间的区别:

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)

对于第一个元素R有赋值和专有名称,而第二个元素的名称看起来有点奇怪。

str(df)
# 'data.frame': 10 obs. of  2 variables:
#  $ a             : num  0.6393 1.125 -1.2514 0.0729 -1.3292 ...
#  $ b....rnorm.10.: num  0.2485 0.0391 -1.6532 -0.3366 1.1951 ...

R版本3.3.2 (2016-10-31);macOS Sierra 10.12.1