->(右箭头)和 <-(左箭头)在 for 循环中的不同行为

Ale*_*lok 3 language-design r

从 R3.0 开始,for循环返回NULL(如文档所述):

x <- for(i in 1:3) {i+1}
x
# NULL
Run Code Online (Sandbox Code Playgroud)

但是,使用右箭头赋值,它似乎返回最后一个值:

for(i in 1:3) {i+1} -> x
x
# [1] 4
Run Code Online (Sandbox Code Playgroud)

该文档没有评论->,并且正如 Ben Bolker 所指出的那样,->似乎<-无论如何都转换为:

expression(1 -> x)
# expression(x <- 1)
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  1. 这是错误还是误解?
  2. 如果它们应该相同,为什么会->与<-这种情况下的行为不同?

MrF*_*ick 7

实际上,我认为这更多是解析问题。命令

for(i in 1:3) {i+1} -> x
Run Code Online (Sandbox Code Playgroud)

实际上被解析为类似的东西

for(i in 1:3) {
   x <- {i+1}
}
Run Code Online (Sandbox Code Playgroud)

您可以在lobstr包的帮助下在 AST 中看到这一点

lobstr::ast(for(i in 1:3) {i+1} -> x)
o-`for` 
+-i 
+-o-`:` 
| +-1 
| \-3 
\-o-`<-` 
  +-x 
  \-o-`{` 
    \-o-`+` 
      +-i 
      \-1 
Run Code Online (Sandbox Code Playgroud)

所以赋值是循环体的一部分。例如,您也可以毫无错误地运行它

for(i in 1:3) {i+1} ^2
Run Code Online (Sandbox Code Playgroud)

或者看看你从这个表达中得到了什么

for(i in 1:3) {i+1} + {print(i)}
# [1] 1
# [1] 2
# [1] 3
Run Code Online (Sandbox Code Playgroud)

循环体表达式不会在第一个大括号的末尾终止。它在行尾结束(或者您可以以 a;或通过将其嵌套在代码块中来结束)。这在任何方面都不是赋值运算符所独有的。

所以这不是一个错误,它只是有点令人困惑的语法。你期待的看起来更像

{for(i in 1:3) {i+1}} -> x
Run Code Online (Sandbox Code Playgroud)

仍然返回NULL。