问题 在R中创建表达式树


替代函数 R 以树的形式创建一个可以解析的语言对象。如何使用列表从头开始创建树,或者然后将其提供给eval?

# substitute gives a tree representation of the expression
a=1; b=2;
e1 = substitute(a+2*b)
eval(e1)      #gives 5 as expected
e1            # is type language
e1[[1]]       # this is `+`
e1[[2]]       # this is 'a' type symbol
e1[[3]]       # this is type language
e1[[3]][[1]]  # this is `*`  etc....

我想知道如何重建 e1 以编程方式对象。理想情况下,我创建了一个复杂列表的对象,其中包含正确的对象,也许我会调用一些 as.language 在...上 list 目的。然而,这不起作用。例如:

# how to construct the tree?
eval(list(as.symbol('+'),1,1))                # does not return 2
eval(as.expression(list(as.symbol('+'),1,1))) # does not return 2

一种方法是生成字符串'1 + 1'然后解析它,但是当你首先拥有树时,生成字符串以再次解析它们似乎并不优雅!

eval(parse(text='1+1')) # does return 1, but not elegant if tree is 
                        # large and already in memory 

谢谢你的帮助!


11967
2017-12-22 22:12


起源



答案:


> plus <- .Primitive("+")
> plus
function (e1, e2)  .Primitive("+")
> times=.Primitive("*")
> eval(call("plus", b, call("times",2, b)))
[1] 6
> eval(call("plus", a, call("times",2, b)))
[1] 5

7
2017-12-22 23:14



甚至更好,所以我可以做到 call('+',e1,e2) 结合2表达与加号,完美! - tlamadon


答案:


> plus <- .Primitive("+")
> plus
function (e1, e2)  .Primitive("+")
> times=.Primitive("*")
> eval(call("plus", b, call("times",2, b)))
[1] 6
> eval(call("plus", a, call("times",2, b)))
[1] 5

7
2017-12-22 23:14



甚至更好,所以我可以做到 call('+',e1,e2) 结合2表达与加号,完美! - tlamadon


有几种方法可以编程方式构造R表达式。如果适用于您的情况,最方便的是 bquote

> a = 1
> bquote(.(a) + .(a))
1 + 1

哪里 .() 是一个反向引用。这应该适用于任何事情,但如果没有,有办法手动构建表达式的基本构建块:

> as.symbol('f')
f
> as.call(list(quote(f), 1, 2))
f(1, 2)
> as.call(list(as.symbol('{'), 1, 2))
{
    1
    2
}
> 

8
2017-12-22 23:09



大, as.call 实际上我正在寻找。从2个表达式如何将它们组合成第三个和 as.call(list(as.symbol('+'),e1,e2)) 作品 - tlamadon