Is it possible to remove an element from ... and pass ... onto other functions? My first two attempts failed:
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 )
Edit
Sorry about the confusion. I fixed child(). The intent was to have child list the contents of ...
Edit2
Here's more of a real-world example (but still fairly simple so we can have a useful conversation about it). Parent is called via recursion. Parent need to know the depth of the recursive call. Callers outside of parent should't know about "depth" nor should they set it when calling parent(). Parent calls other functions, in this case child(). Child needs values in ... Clearly child doesn't need "depth" because parent generated it for its own use.
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
}
One way to manipulate these things is to wrap the child
function inside parent
, and use a definition that puts any arguments you don't want passing on to child
after the ...
argument. For example:
parent <- function(...) {
localChild <- function(..., toRemove) child(...)
localChild(...)
}
child <- function(a) {
a + 10
}
> parent(a = 1, toRemove = 10)
[1] 11
Another way is to use 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
Depending on your actual use case, the do.call()
is perhaps closest to what you intended with your Question.
Your child function is erroneous. Try
> child(a=1)
Error in str(a) : object 'a' not found
edit : no longer applicable.
The ... argument should only be used to pass parameters to a next function. You cannot get the parameters from there that easily, unless you convert them to a list. So your child function could be :
child <- function(...)
{
mc <- match.call() # or mc <- list(...)
str(mc$a)
}
Which doesn't make sense. You can't know whether the user specified a
or not. The correct way would be to include a
as an argument in your function. the ...
is to pass arguments to the next one :
child <- function(a, ...){
str(a,...)
}
Then you could do :
parent <- function(...){
mc <- match.call()
mc$toRemove <- NULL
mc[[1L]] <- as.name("child")
eval(mc)
}
or use the list(...)
and do.call()
construct @Gavin proposed. The benefit of match.call()
is that you can include non-dot arguments as well. This allows your parent function to specify defaults for the child :
parent <- function(a=3, ...){
... (see above)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With