“=”和“=”之间有什么区别?和“<-”赋值运算符?

发布于 2024-08-11 04:01:10 字数 252 浏览 11 评论 0原文

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

我知道运算符略有不同,如本示例所示,

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

但这是唯一的区别吗?

What are the differences between the assignment operators = and <- in R?

I know that operators are slightly different, as this example shows

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

But is this the only difference?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

泪冰清 2024-08-18 04:01:10

当您使用赋值运算符设置参数值时,它们之间的区别会更加明显函数调用。例如:

median(x = 1:10)
x   
## Error: object 'x' not found

在本例中,x 是在函数范围内声明的,因此它不存在于用户工作区中。

median(x <- 1:10)
x    
## [1]  1  2  3  4  5  6  7  8  9 10

在本例中,x 是在用户工作空间中声明的,因此您可以在函数调用完成后使用它。


R 社区普遍倾向于使用 <- 进行赋值(函数签名除外),以与(非常)旧版本的 S-Plus 兼容。请注意,空格有助于澄清情况,例如

x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3

大多数 R IDE 都有键盘快捷键,使 <- 更容易键入。 Architect 中的 Ctrl + =,RStudio 中的 Alt + - (Option + < kbd>-(macOS 下),Shift + -(下划线)在 emacs+ESS 中。


如果您更喜欢将 = 写入 <-,但希望对公开发布的代码使用更常见的赋值符号(例如,在 CRAN 上),那么您可以使用以下之一formatR 中的 tidy_* 函数 包自动将 = 替换为 <-

library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5

“为什么 x <- y = 5 会抛出错误,但 x <- y <- 5 不会?”这个问题的答案是“这取决于解析器中包含的魔力”。 R 的语法包含 许多模棱两可的情况必须以某种方式解决。解析器根据是否使用 =<- 来选择以不同顺序解析表达式的位。

要了解发生了什么,您需要知道赋值会默默地返回所分配的值。您可以通过显式打印来更清楚地看到这一点,例如 print(x <- 2 + 3)

其次,如果我们使用前缀表示法进行赋值会更清楚。所以

x <- 5
`<-`(x, 5)  #same thing

y = 5
`=`(y, 5)   #also the same thing

解析器将 x <- y <- 5 解释为

`<-`(x, `<-`(y, 5))

我们可能期望 x <- y = 5

`<-`(x, `=`(y, 5))

但实际上它被解释为

`=`(`<-`(x, y), 5)

这是因为 = 的优先级低于 <-,如 ?语法帮助页面。

The difference in assignment operators is clearer when you use them to set an argument value in a function call. For example:

median(x = 1:10)
x   
## Error: object 'x' not found

In this case, x is declared within the scope of the function, so it does not exist in the user workspace.

median(x <- 1:10)
x    
## [1]  1  2  3  4  5  6  7  8  9 10

In this case, x is declared in the user workspace, so you can use it after the function call has been completed.


There is a general preference among the R community for using <- for assignment (other than in function signatures) for compatibility with (very) old versions of S-Plus. Note that the spaces help to clarify situations like

x<-3
# Does this mean assignment?
x <- 3
# Or less than?
x < -3

Most R IDEs have keyboard shortcuts to make <- easier to type. Ctrl + = in Architect, Alt + - in RStudio (Option + - under macOS), Shift + - (underscore) in emacs+ESS.


If you prefer writing = to <- but want to use the more common assignment symbol for publicly released code (on CRAN, for example), then you can use one of the tidy_* functions in the formatR package to automatically replace = with <-.

library(formatR)
tidy_source(text = "x=1:5", arrow = TRUE)
## x <- 1:5

The answer to the question "Why does x <- y = 5 throw an error but not x <- y <- 5?" is "It's down to the magic contained in the parser". R's syntax contains many ambiguous cases that have to be resolved one way or another. The parser chooses to resolve the bits of the expression in different orders depending on whether = or <- was used.

To understand what is happening, you need to know that assignment silently returns the value that was assigned. You can see that more clearly by explicitly printing, for example print(x <- 2 + 3).

Secondly, it's clearer if we use prefix notation for assignment. So

x <- 5
`<-`(x, 5)  #same thing

y = 5
`=`(y, 5)   #also the same thing

The parser interprets x <- y <- 5 as

`<-`(x, `<-`(y, 5))

We might expect that x <- y = 5 would then be

`<-`(x, `=`(y, 5))

but actually it gets interpreted as

`=`(`<-`(x, y), 5)

This is because = is lower precedence than <-, as shown on the ?Syntax help page.

多像笑话 2024-08-18 04:01:10

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

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

<前><代码>...
'-> ->>'向右赋值
'<- <<-' 赋值(从右到左)
'=' 赋值(从右到左)
……

但这是唯一的区别吗?

既然您问的是赋值运算符:是的,这是唯一的区别。然而,如果您不这么认为,也情有可原。甚至 R 文档 ?assignOps< /a> 声称还有更多差异:

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

我们不要过分强调:R 文档是错误的。这很容易证明:我们只需要找到 = 运算符的反例,该运算符既不是 (a) 顶层,也不是 (b) 括号表达式列表中的子表达式(即 {...; ...})。 — 言归正传:

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

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

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

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

那么 R 如何决定 = 的给定用法是指运算符还是指命名参数传递呢?让我们来看看。

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

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

= 是定义命名参数传递的标记:它不是赋值运算符。此外,在某些语法上下文中,= 是完全被禁止的

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

其中任何一个都会引发错误“在中出现意外的'='”。

在任何其他上下文中,= 指的是赋值运算符调用。特别是,仅仅在子表达式两边加上括号就可以使上述 (a) 有效,以及 (b) 赋值。例如,以下代码执行赋值:

median((x = 1 : 10))

而且:

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

现在您可能会反对这样的代码是残暴的(您可能是对的)。但我从 base::file.copy 函数中获取了这段代码(用 = 替换 <-)——这是一种普遍的模式在大部分核心 R 代码库中。

John Chambers 的原始解释, R 文档可能基于该文档,实际上正确地解释了这一点:

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


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

What are the differences between the assignment operators = and <- in R?

As your example shows, = and <- have slightly different operator precedence (which determines the order of evaluation when they are mixed in the same expression). In fact, ?Syntax in R gives the following operator precedence table, from highest to lowest:

…
‘-> ->>’           rightwards assignment
‘<- <<-’           assignment (right to left)
‘=’                assignment (right to left)
…

But is this the only difference?

Since you were asking about the assignment operators: yes, that is the only difference. However, you would be forgiven for believing otherwise. Even the R documentation of ?assignOps claims that there are more differences:

The operator <- can be used anywhere,
whereas the operator = is only allowed at the top level (e.g.,
in the complete expression typed at the command prompt) or as one
of the subexpressions in a braced list of expressions.

Let’s not put too fine a point on it: the R documentation is wrong. This is easy to show: we just need to find a counter-example of the = operator that isn’t (a) at the top level, nor (b) a subexpression in a braced list of expressions (i.e. {…; …}). — Without further ado:

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

Clearly we’ve performed an assignment, using =, outside of contexts (a) and (b). So, why has the documentation of a core R language feature been wrong for decades?

It’s because in R’s syntax the symbol = has two distinct meanings that get routinely conflated (even by experts, including in the documentation cited above):

  1. The first meaning is as an assignment operator. This is all we’ve talked about so far.
  2. The second meaning isn’t an operator but rather a syntax token that signals named argument passing in a function call. Unlike the = operator it performs no action at runtime, it merely changes the way an expression is parsed.

So how does R decide whether a given usage of = refers to the operator or to named argument passing? Let’s see.

In any piece of code of the general form …

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

… the = is the token that defines named argument passing: it is not the assignment operator. Furthermore, = is entirely forbidden in some syntactic contexts:

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

Any of these will raise an error “unexpected '=' in ‹bla›”.

In any other context, = refers to the assignment operator call. In particular, merely putting parentheses around the subexpression makes any of the above (a) valid, and (b) an assignment. For instance, the following performs assignment:

median((x = 1 : 10))

But also:

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

Now you might object that such code is atrocious (and you may be right). But I took this code from the base::file.copy function (replacing <- with =) — it’s a pervasive pattern in much of the core R codebase.

The original explanation by John Chambers, which the the R documentation is probably based on, actually explains this correctly:

[= assignment is] allowed in only two places in the grammar: at the top level (as a complete program or user-typed expression); and when isolated from surrounding logical structure, by braces or an extra pair of parentheses.


In sum, by default the operators <- and = do the same thing. But either of them can be overridden separately to change its behaviour. By contrast, <- and -> (left-to-right assignment), though syntactically distinct, always call the same function. Overriding one also overrides the other. Knowing this is rarely practical but it can be used for some fun shenanigans.

缺⑴份安定 2024-08-18 04:01:10

Google 的 R 风格指南通过禁止使用“=”进行赋值来简化问题。不错的选择。

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

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

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

Google's R style guide simplifies the issue by prohibiting the "=" for assignment. Not a bad choice.

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

The R manual goes into nice detail on all 5 assignment operators.

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

说好的呢 2024-08-18 04:01:10

x = y = 5 相当于 x = (y = 5),因为赋值运算符从右到左“分组”,这是有效的。含义:将5赋值给y,留下数字5;然后将 5 分配给 x。

这与 (x = y) = 5 不同,后者不起作用!含义:将y的值赋给x,留下y的值;然后将 5 分配给,嗯...,到底是什么?

当混合使用不同类型的赋值运算符时,<- 的绑定比 = 更紧密。因此,x = y <- 5 被解释为 x = (y <- 5),这种情况是有意义的。

不幸的是,x <- y = 5 被解释为 (x <- y) = 5,这种情况不起作用!

请参阅 ?Syntax?assignOps 了解优先级(绑定)和分组规则。

x = y = 5 is equivalent to x = (y = 5), because the assignment operators "group" right to left, which works. Meaning: assign 5 to y, leaving the number 5; and then assign that 5 to x.

This is not the same as (x = y) = 5, which doesn't work! Meaning: assign the value of y to x, leaving the value of y; and then assign 5 to, umm..., what exactly?

When you mix the different kinds of assignment operators, <- binds tighter than =. So x = y <- 5 is interpreted as x = (y <- 5), which is the case that makes sense.

Unfortunately, x <- y = 5 is interpreted as (x <- y) = 5, which is the case that doesn't work!

See ?Syntax and ?assignOps for the precedence (binding) and grouping rules.

匿名。 2024-08-18 04:01:10

根据 John Chambers 的说法,运算符 = 只允许在“顶层”使用,这意味着它在 if 这样的控制结构中是不允许的,从而导致以下编程错误非法。

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

正如他所写,“在控制表达式中禁止使用新的赋值形式 [=] 可以避免使用 equal 运算符比使用其他 S 赋值更容易出现编程错误(例如上面的示例)。”

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

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

According to John Chambers, the operator = is only allowed at "the top level," which means it is not allowed in control structures like if, making the following programming error illegal.

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

As he writes, "Disallowing the new assignment form [=] in control expressions avoids programming errors (such as the example above) that are more likely with the equal operator than with other S assignments."

You can manage to do this if it's "isolated from surrounding logical structure, by braces or an extra pair of parentheses," so if ((x = 0)) 1 else x would work.

See http://developer.r-project.org/equalAssign.html

清晨说晚安 2024-08-18 04:01:10

来自官方 R 文档

运算符 <-= 分配到它们所在的环境中
被评估。运算符 <- 可以在任何地方使用,
运算符 = 只允许在顶层
(例如,在
在命令提示符下键入的完整表达式)或作为其中之一
大括号表达式列表中的子表达式。

From the official R documentation:

The operators <- and = assign into the environment in which they
are evaluated. The operator <- can be used anywhere, whereas the
operator = is only allowed at the top level
(e.g., in the
complete expression typed at the command prompt) or as one of the
subexpressions in a braced list of expressions.

怀中猫帐中妖 2024-08-18 04:01:10

这也可能有助于理解这两个运算符之间的差异:

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 塞拉利昂 10.12.1

This may also add to understanding of the difference between those two operators:

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

For the first element R has assigned values and proper name, while the name of the second element looks a bit strange.

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 version 3.3.2 (2016-10-31); macOS Sierra 10.12.1

吻泪 2024-08-18 04:01:10

我不确定这里是否引用了 Patrick Burns 的书《R inferno》,其中 8.2.26 = 不是 <- 的同义词 Patrick 指出“你显然不想使用 '<-'当你想设置函数的参数时。”。该书可在 https://www.burns-stat 获取。 com/documents/books/the-r-inferno/

I am not sure if Patrick Burns book R inferno has been cited here where in 8.2.26 = is not a synonym of <- Patrick states "You clearly do not want to use '<-' when you want to set an argument of a function.". The book is available at https://www.burns-stat.com/documents/books/the-r-inferno/

只是我以为 2024-08-18 04:01:10

<-= 在过去的 R 版本甚至 R 的前身语言(S 语言)中都存在一些差异。但目前,似乎仅像任何其他现代语言(python、java)一样使用 = 不会导致任何问题。在将值传递给某些扩展时,您可以通过使用 <- 来实现更多功能,同时创建全局变量,但它可能会出现奇怪/不需要的行为,如

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)
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 ...

强烈推荐!尝试阅读这篇文章,这是试图解释两者之间差异的最佳文章:
检查 https://colinfay.me/r-assignment/

另外,考虑一下 < ;- 作为一个隐式返回值的函数。

a <- 2
(a <- 2)
#> [1] 2

请参阅:https://adv-r.hadley.nz/functions.html

There are some differences between <- and = in the past version of R or even the predecessor language of R (S language). But currently, it seems using = only like any other modern language (python, java) won't cause any problem. You can achieve some more functionality by using <- when passing a value to some augments while also creating a global variable at the same time but it may have weird/unwanted behavior like in

df <- data.frame(
      a = rnorm(10),
      b <- rnorm(10)
)
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 ...

Highly recommended! Try to read this article which is the best article that tries to explain the difference between those two:
Check https://colinfay.me/r-assignment/

Also, think about <- as a function that invisibly returns a value.

a <- 2
(a <- 2)
#> [1] 2

See: https://adv-r.hadley.nz/functions.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文