方法调度缺少参数(Method dispatch with missing arguments)

编程入门 行业动态 更新时间:2024-10-28 13:13:48
方法调度缺少参数(Method dispatch with missing arguments)

如何在给定S4方法中明确地将参数值分派给后续S4方法时,如何避免经典Error: argument "<argname>" is missing, with no default错误(参见下面的示例)。


大图

有一个方法foo()调用方法bar() 。 两种方法都依赖于参数x和y 。 方法foo()以显式方式将参数x和y调度到bar() : bar(x=x, y=y) 。

现在,关键点在于我不希望foo()关注是否缺少传递给bar()任何或所有参数。

通用方法

setGeneric( name="foo", signature=c("x", "y"), def=function(x, y, ...) { standardGeneric("foo") } ) setGeneric( name="bar", signature=c("x", "y"), def=function(x, y, ...) { standardGeneric("bar") } )

bar()方法bar()

setMethod( f="bar", signature=signature(x="missing", y="missing"), definition=function(x, y, ...) { print("Doing what I'm supposed to do when both args are missing") return(NULL) } ) setMethod( f="bar", signature=signature(x="ANY", y="missing"), definition=function(x, y, ...) { message("'y' is missing, but I can give you 'x':") print(x) return(NULL) } ) setMethod( f="bar", signature=signature(x="missing", y="ANY"), definition=function(x, y, ...) { message("'x' is missing, but I can give you 'y':") print(y) return(NULL) } ) setMethod( f="bar", signature=signature(x="ANY", y="ANY"), definition=function(x, y, ...) { message("x:") print(x) message("y:") print(y) return(NULL) } )

foo()

如上所述,我不希望foo()关注是否缺少传递给bar()任何或所有参数。 它应该以明确的方式将所有内容传递给bar() :

setMethod( f="foo", signature=signature(x="ANY", y="ANY"), definition=function(x, y, ...) { bar(x=x, y=y) } )

解决方法

到目前为止,这是我能提出的唯一解决方法:

setMethod( f="foo", signature=signature(x="ANY", y="ANY"), definition=function(x, y, ...) { if (missing(x) && missing(y)) { bar() } else if (missing(x)) { bar(y=y) } else if (missing(y)) { bar(x=x) } else { bar(x=x, y=y) } } ) > foo(x="Hello", y="World!") x: [1] "Hello" y: [1] "World!" NULL > foo(x="Hello") 'y' is missing, but I can give you 'x': [1] "Hello" NULL > foo(y="World!") 'x' is missing, but I can give you 'y': [1] "World!" NULL > foo() [1] "Doing what I'm supposed to do when both args are missing" NULL

Big picture

Whe have a method foo() that calls method bar(). Both methods depend on arguments x and y. Method foo() dispatches arguments x and y to bar() in an explicit way: bar(x=x, y=y).

Now, the crucial point here is that I don't want foo() to care if any or all of the arguments that are passed along to bar() are missing.

Generic methods

setGeneric( name="foo", signature=c("x", "y"), def=function(x, y, ...) { standardGeneric("foo") } ) setGeneric( name="bar", signature=c("x", "y"), def=function(x, y, ...) { standardGeneric("bar") } )

Methods for bar()

setMethod( f="bar", signature=signature(x="missing", y="missing"), definition=function(x, y, ...) { print("Doing what I'm supposed to do when both args are missing") return(NULL) } ) setMethod( f="bar", signature=signature(x="ANY", y="missing"), definition=function(x, y, ...) { message("'y' is missing, but I can give you 'x':") print(x) return(NULL) } ) setMethod( f="bar", signature=signature(x="missing", y="ANY"), definition=function(x, y, ...) { message("'x' is missing, but I can give you 'y':") print(y) return(NULL) } ) setMethod( f="bar", signature=signature(x="ANY", y="ANY"), definition=function(x, y, ...) { message("x:") print(x) message("y:") print(y) return(NULL) } )

Method for foo()

As mentioned above, I don't want foo() to care if any or all of the arguments that are passed along to bar() are missing. It is just supposed to pass everything along to bar() in an explicit manner:

setMethod( f="foo", signature=signature(x="ANY", y="ANY"), definition=function(x, y, ...) { bar(x=x, y=y) } )

Workaround

This is the only workaround that I could come up with so far:

setMethod( f="foo", signature=signature(x="ANY", y="ANY"), definition=function(x, y, ...) { if (missing(x) && missing(y)) { bar() } else if (missing(x)) { bar(y=y) } else if (missing(y)) { bar(x=x) } else { bar(x=x, y=y) } } ) > foo(x="Hello", y="World!") x: [1] "Hello" y: [1] "World!" NULL > foo(x="Hello") 'y' is missing, but I can give you 'x': [1] "Hello" NULL > foo(y="World!") 'x' is missing, but I can give you 'y': [1] "World!" NULL > foo() [1] "Doing what I'm supposed to do when both args are missing" NULL

It works, but I don't really like it because of all the if ... else statements. The whole "if-else logic" already went in the specification of the various methods for bar(). After all, that's the whole point of having a method dispatcher in the first place, right? Hence I would consider the statements as "undesired work" and I'm looking for a better way.

One could of course resort to to using NULL as default value for all "critical" arguments, but I would like to rely on missing() instead of is.null() in my functions as much as possible.

最满意答案

这是另一种想法。 (它广泛受到许多R模型拟合函数所使用的“语言计算”的启发。)

setMethod( f="foo", signature=signature(x="ANY", y="ANY"), definition=function(x, y, ...) { mc <- match.call() mc[[1]] <- quote(bar) eval(mc) } ) foo(x="Hello") # 'y' is missing, but I can give you 'x': # [1] "Hello" # NULL foo(y="World") # 'x' is missing, but I can give you 'y': # [1] "World" # NULL foo() # [1] "Doing what I'm supposed to do when both args are missing" # NULL

Here is an alternative idea. (It's broadly inspired by the sort of "computing on the language" used by many of R's model-fitting functions.)

setMethod( f="foo", signature=signature(x="ANY", y="ANY"), definition=function(x, y, ...) { mc <- match.call() mc[[1]] <- quote(bar) eval(mc) } ) foo(x="Hello") # 'y' is missing, but I can give you 'x': # [1] "Hello" # NULL foo(y="World") # 'x' is missing, but I can give you 'y': # [1] "World" # NULL foo() # [1] "Doing what I'm supposed to do when both args are missing" # NULL

更多推荐

本文发布于:2023-08-06 18:16:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1454169.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:参数   方法   Method   arguments   missing

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!