这只是我编写的更复杂代码的MWE。
假设我想创建一个新方法newMethod
,其中(除其他外)需要从数据框x
中提取变量data
,但还需要从中提取一些其他属性data
(例如,其列名)。
我首先将S3泛型定义如下
newMethod <- function(x, data) UseMethod("newMethod")
为了从x
data
中提取newMethod.default
,我写了newMethod.default <- function(x, data) {
x <- eval(substitute(x), envir = data)
return(list(x = x, names = names(data)))
}
:
class(x)
根据newMethod.default
我计划进一步调度(可能在newMethod(mpg, mtcars)
内,然后返回列表),但这在这里并不重要(我在这里只是提一下来解释一下)为什么我首先要创建一个通用函数。)
但是,当我通过运行
来测试这个泛型时Error in newMethod(mpg, mtcars) : object 'mpg' not found
我得到(可能并不奇怪)错误消息:newMethod.default
。所以现在我想知道什么是最好的解决方法。我的直觉是将部分代码从newMethod
移到newMethod <- function(x, data) {
x <- eval(substitute(x), envir = data)
UseMethod("newMethod", x)
}
,就像我在这里一样
newMethod.default
但我不太确定这是普通的还是好的做法,部分原因是it's suggested not to use the second argument of UseMethod
。另外,我需要保持{{1}}的第一行不变,否则我会再次收到错误消息。
如果有人能指出我正确的方向,我会非常感激,因为我觉得我并没有在这个方向上走得很好。非常感谢提前!
答案 0 :(得分:1)
发生这种情况的原因与该方法无关,而只是与R如何读取代码有关。它查看第一个参数并决定基于此进行一些调度。但问题是这个对象mpg
不存在,所以R无法决定应该调用什么方法。 R需要能够确定该对象的类。 &#34;不存在&#34;不是一个类,因此不可能在调用函数的环境中不存在的对象上发送。
查看with()
函数和defaut方法with.default()
。这基本上完成了你在这里做的事情,但更多的是一般方式。它的默认方法实际上与您的示例几乎完全相同:
> with.default
function (data, expr, ...)
eval(substitute(expr), data, enclos = parent.frame())
<bytecode: 0x0825d7d8>
<environment: namespace:base>
重要的一点是with()
将数据参数作为第一个参数,而表达式(在您的情况下只是mpg
)作为第二个参数。这样,mpg
在调用框架中不存在并不重要,因为R只在查看调度时查看第一个参数。
这样可行:
newMethod <- function( data, x) UseMethod("newMethod")
newMethod.default <- function(data, x) {
x <- eval(substitute(x), envir = data)
return(list(x = x, names = names(data)))
}
旁注:再次考虑从newMethod.default
内部发送的事件。不确定你到底想要实现什么,但我觉得这是你可以使用NextMethod
的东西。但这是一项棘手的工作,在这种情况下,转移到S4可能会更方便,原因很简单,您可以将S4方法用于类的组合甚至是缺少参数。但是只要你留在S3中,除了在泛型函数中使用exists()
之外,没有办法捕获不存在的对象,例如:
newMethod <- function( data, x) {
if(exists(deparse(substitute(x))))
UseMethod("newMethod")}
但这是我不会自己使用的代码。