如何在评估之前使用反射来拦截表达式?

时间:2015-01-28 01:12:01

标签: r reflection

我希望在评估之前使用R的反射功能拦截评估中的当前表达式。

例如,要创建一些语法糖,请给出以下内容:

> Server <- setRefClass("Server",
>   methods = list(
>       handler = function(expr) submitExpressionToRemoteServer(expr)
>   )
> )
> server <- Server()
> server$foo$bar$baz    #... should be map to...    server$handler("foo$bar$baz")

我希望server$foo$bar$baz方法拦截表达式server$handler,并将其映射到server$handler("foo$bar$baz")

请注意,即使未定义server$foo,我也希望此调用成功:我只对表达式本身感兴趣(所以我可以使用表达式做事),而不是它计算为有效的本地对象。

这可能吗?

1 个答案:

答案 0 :(得分:2)

我不认为可以使用R中的Reference Classes(R5)对象重新定义$行为。但是,这可以用S4类来完成。主要问题是像

这样的表达式
server$foo$bar$baz 

会转换为一系列调用,例如

$($($(server,"foo"),"bar"),"baz")

但与普通函数嵌套不同,在进入下一级嵌套之前,每个内部调用似乎都已完全评估。在第一个$之后拆分所有内容并不是真的可能,因为它不是如何解析的。但是,您可以让$函数返回另一个对象,并附加发送给该对象的所有值。这是一个样本S4类

setClass("Server", slots=list(el="character"))
setMethod("$", signature(x="Server"), 
   function(x,name) {
    xx <- append(slot(x,"el"),name)
    new("Server", el=xx)
   }
)

server <- new("Server")    
server$foo$bar$baz

# An object of class "Server"
# Slot "el":
# [1] "foo"   "bar" "baz"

唯一的问题是,如果您想对这些参数做任何事情,我无法知道您何时在列表的末尾。