是否可以从...中删除元素并将...传递给其他函数?我的前两次尝试失败了:
parent = function(...)
{
a = list(...)
str(a)
a$toRemove = NULL
str(a)
# attempt 1
child(a)
# attempt 2
child( ... = a )
}
child = function(...)
{
a = list( ... )
str(a)
}
parent( a = 1 , toRemove = 2 )
修改的
对此感到抱歉。我修了孩子()。目的是让孩子列出......的内容。
EDIT2
这里有一个真实的例子(但仍然相当简单,所以我们可以就此进行有用的对话)。父通过递归调用。父需要知道递归调用的深度。父母以外的来电者不应该知道“深度”,也不应该在调用parent()时设置它。 Parent调用其他函数,在本例中为child()。孩子需要值...显然,孩子不需要“深度”,因为父母为自己的用途生成了它。
parent = function( ... )
{
depth = list(...)$depth
if ( is.null( depth ) )
{
depth = 1
}
print( depth )
# parent needs value of depth to perform various calculations (not shown here)
if ( depth == 5 )
{
return()
}
else
{
# child doesn't need "depth" in ...
child( ... )
}
# yikes! now we've added a second, third, etc. depth value to ...
parent( depth = depth + 1 , ... )
}
child = function(...)
{
# does some magic
}
答案 0 :(得分:24)
操纵这些东西的一种方法是将child
函数包装在parent
中,并使用一个定义,将您不想传递的任何参数传递给child
在 ...
参数之后。例如:
parent <- function(...) {
localChild <- function(..., toRemove) child(...)
localChild(...)
}
child <- function(a) {
a + 10
}
> parent(a = 1, toRemove = 10)
[1] 11
另一种方法是使用do.call()
:
parent2 <- function(...) {
a <- list(...)
a$toRemove <- NULL
do.call(child2, a)
}
child2 <- function(b) {
b + 10
}
> parent2(b = 1, toRemove = 10)
[1] 11
根据您的实际使用情况,do.call()
可能与您对问题的意图最接近。
答案 1 :(得分:5)
您的孩子功能有误。尝试
> child(a=1)
Error in str(a) : object 'a' not found
编辑:不再适用。
...参数只应用于将参数传递给下一个函数。除非将它们转换为列表,否则无法从中轻松获取参数。所以你的孩子的功能可能是:
child <- function(...)
{
mc <- match.call() # or mc <- list(...)
str(mc$a)
}
哪个没有意义。您无法知道用户是否指定了a
。正确的方法是在函数中包含a
作为参数。 ...
是将参数传递给下一个参数:
child <- function(a, ...){
str(a,...)
}
然后你可以这样做:
parent <- function(...){
mc <- match.call()
mc$toRemove <- NULL
mc[[1L]] <- as.name("child")
eval(mc)
}
或使用list(...)
和do.call()
构造@Gavin建议。 match.call()
的好处是你也可以包含非点参数。这允许您的父函数指定子项的默认值:
parent <- function(a=3, ...){
... (see above)
}
答案 2 :(得分:4)
这是一个如何从...中取出项目并删除元素然后用do.call调用下一个函数的示例:
parent <- function(...){
funArgs <- list(...)
str(funArgs)
## remove the second item
newArgs <- funArgs[-2]
str(newArgs)
## if you want to call another function, use do.call
do.call(child, newArgs)
}
child = function(...)
{
cat("Don't call me a child, buddy!\n")
a <- list(...)
str(a)
}
parent(a=1, b=2, c=3)
如果您需要向参数添加更多项目,而不是删除参数,请记住do.call
喜欢命名列表,其中名称是参数名称,列表值是参数值。这是在帮助文件中,但在最终搞清楚之前我一直在努力。
答案 3 :(得分:3)
你得到了一些很好的答案,但这里有一些简单的东西可以解决你的具体例子:
parent = function(...)
{
a = list(...)
str(a)
a$toRemove = NULL
str(a)
# attempt 1
child(a)
# attempt 2
#child(...)
}
child = function(...)
{
a <- as.list(...)
str(a)
}
parent( a = 1 , toRemove = 2 )
返回:
List of 2
$ a : num 1
$ toRemove: num 2
List of 1
$ a: num 1
List of 1
$ a: num 1
您的原始版本引发了错误,因为a
中未定义child
。然后,只需在as.list(...)
中使用child
(而不仅仅是list(...)
)就可以生成所需的输出。请注意,我只在这里使用您的尝试。
答案 4 :(得分:0)
我不认为列出的答案可以解决问题,或者至少不会像我读到的那样解决问题。假设您想将一些参数(如'xmax'和'xmin')作为实际变量传递给子(...)? 在孩子的环境中,它希望看到名为“xmax”和“xmin”的变量,到目前为止提供的示例似乎并没有使这些变量可用。尝试插入像
这样的行xmax-xmin -> xrange
进入child()函数,它会抛出一个错误 我想,原始问题的重点是允许将可选“...”变量的子集传递给child()。您可以针对简单案例定制解决方案,例如: sum(...),其中sum(unlist(the_modified_list))有效。在更一般的情况下,我仍然看不到解决方案。我们可能需要将此问题提升到R-help邮件列表。
上的详细演示文稿