在R语言中解析“->”赋值运算符

17

我想问一下R语言中关于表达式解析的问题。让我举一个例子:

fun_text <- c("
0 -> var
f1 <- function()
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
}

(function()
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
})->f2

f3 = function(x)
{
  0 -> sum_var
  sum_var2 = 0
  sum_var3 <- 0
}

")

fun_tree <- parse(text=fun_text)
fun_tree 
fun_tree[[1]]
fun_tree[[2]]
fun_tree[[3]]
fun_tree[[4]]

完成后,我们得到以下结果:

expression(0 -> var, f1 <- function()
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
}, (function()
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
})->f2, f3 = function(x)
{
    0 -> sum_var
    sum_var2 = 0
    sum_var3 <- 0
})

var <- 0

f1 <- function() {
    sum_var <- 0
    sum_var2 = 0
    sum_var3 <- 0
}

f2 <- (function() {
    sum_var <- 0
    sum_var2 = 0
    sum_var3 <- 0
})

f3 = function(x) {
    sum_var <- 0
    sum_var2 = 0
    sum_var3 <- 0
}

如您所见,所有的“->”赋值运算符都被更改为“<-”,但第一个例子(仅“fun_tree”)没有被更改。我的问题是:为什么会这样?我能确信在语法树中总是得到“<-”运算符,因此我不必在实现“->”情况时费心吗?


你尝试过向r-devel邮件列表询问吗?他们可能会更清楚发生了什么。 - Scott Ritchie
只是出于兴趣,你有检查 length(fun_tree) 确保那里没有更多的“隐藏”吗? - Carl Witthoft
3
@ScottRitchie,我对这个建议不太满意——它会导致 StackOverflow 想要避免的分裂问题。为什么这很重要?首先,SO比邮件列表更容易搜索(或者说更容易被找到)。 - Konrad Rudolph
1
没错,我并不是在暗示这个问题不应该在这里提出。我只是建议另外寻求一些资源来进行参考。 - Scott Ritchie
2个回答

17

我能确定在语法树中总是得到“<-”运算符吗?

让我们看看...

> quote(b -> a)
a <- b
> identical(quote(b -> a), quote(a <- b))
[1] TRUE

是的,-> 赋值符号始终被解析为 <- (但在将 -> 用作函数名时则不成立!1)。

您第一次显示的结果与 parse 函数的 keep.source 参数有关:

> parse(text = 'b -> a')
expression(b -> a)
> parse(text = 'b -> a', keep.source = FALSE)
expression(a <- b)

1当作为函数调用<-时,与作为运算符使用相同:

> quote(`<-`(a, b))
a <- b
> identical(quote(a <- b), quote(`<-`(a, b)))
[1] TRUE

然而,虽然你可以定义一个->函数,但是并没有->函数(注:指原生的->函数),因此写b -> a永远不会调用->函数,它总是被解析为a <- b,这将调用<-函数或原始函数。


1
那么,如果 -> 只是在解析过程中被反转,它存在的历史背景是什么? - Thomas
@Thomas我不知道原因。有时我在R的REPL中使用它,因为我通过逐步构建长表达式(即慢慢地构建它)并想将其结果分配给变量而无需重新输入或将光标放回行首。懒人,确实如此。有一些语言(TI BASIC)具有从左到右的赋值符号(42 → x)。 - Konrad Rudolph
我同意Konrad的观点,认为使用->的原因是为了方便。虽然在脚本中不应该使用它,但如果你在命令行上,当你忘记将其分配给某个变量时,在行末添加-> myvar更容易,并且R确实提供了一些仅存在于命令行上以使您的生活更轻松的功能。 - Dason
2
一个有点离题的好奇心:你知道R曾经允许使用“_”进行赋值吗?这在R 1.8.0中已被删除 - gagolews
请参考这个问答,了解更详细的->解析方式。 - MichaelChirico

0

这可能有点偏题,但我认为从左到右的赋值运算符可以用于除了快速命令行输入之外的情况。因此,以下是定义这种运算符的一种方法:

"%op%"<- function(a,b) eval(substitute(b<-a), parent.frame())

我使用这个方法来避免在将一组矩阵和向量存储/加载到向量中时重复编写R代码(错误:在R中未找到对象'->')。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接