如何在评估之前使用反射来拦截表达式?
How to use reflection to intercept an expression prior to evaluation?
我希望在计算之前使用 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
,我也希望此调用成功:我只对 表达式本身感兴趣 (因此我可以使用表达式),而不是它计算为有效的本地对象。
这可能吗?
我认为用 R 中的参考 类 (R5) 对象重新定义 $
行为是不可能的。但是,您可以使用 S4 [=24] =]是的。主要问题是像
这样的表达式
server$foo$bar$baz
会被翻译成一系列调用,例如
$($($(server,"foo"),"bar"),"baz")
但与普通函数嵌套不同的是,每个内部调用在进入下一层嵌套之前似乎都经过了全面评估。这真的不可能仅仅在第一个 $
之后拆分所有内容,因为这不是它的解析方式。但是,您可以让 $
函数 return 另一个对象并将所有值附加到该对象。这是示例 S4 class
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"
唯一的问题是如果您想对这些参数执行任何操作,我无法知道您何时位于列表的末尾。
我希望在计算之前使用 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
,我也希望此调用成功:我只对 表达式本身感兴趣 (因此我可以使用表达式),而不是它计算为有效的本地对象。
这可能吗?
我认为用 R 中的参考 类 (R5) 对象重新定义 $
行为是不可能的。但是,您可以使用 S4 [=24] =]是的。主要问题是像
server$foo$bar$baz
会被翻译成一系列调用,例如
$($($(server,"foo"),"bar"),"baz")
但与普通函数嵌套不同的是,每个内部调用在进入下一层嵌套之前似乎都经过了全面评估。这真的不可能仅仅在第一个 $
之后拆分所有内容,因为这不是它的解析方式。但是,您可以让 $
函数 return 另一个对象并将所有值附加到该对象。这是示例 S4 class
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"
唯一的问题是如果您想对这些参数执行任何操作,我无法知道您何时位于列表的末尾。