Passing along ellipsis arguments to two different functions?
You can pass a list to one of the subfunctions, ie
mainF <- function(f1, f2, ..., args.f2 = list()) {
do.call(f2, c(X=f1(...), args.f2))
}
mainF(function(x) x, function(X, y) X*y, x=5, args.f2 = list(y=3))
(untested, but you got the gist)
R functions: passing arguments with ellipsis
So the ellipses are used to save you specifying all the arguments of f2
in the arguments of f1
. Though when you declare f2
, you still have to treat it like a normal function, so specify the arguments b
and c
.
f1 <- function(a, ...) {
print(a)
f2(...)
}
# Treat f2 as a stand-alone function
f2 <- function(b, c) {
print(b == TRUE)
print(runif(c))
}
f1(2, b=FALSE, c=2)
[1] 2
[1] FALSE
[1] 0.351295 0.9384728
R: Understanding how ellipsis (...) works in nested functions, & how iit doesn't
Ellipsis has to be explicitly provided to pass to a nested function, so for example, in your f02, the list
call gets whatever was passed to f02 as its own arguments. In contrast, in f01, the arguments are simply ignored. You could pass the arguments to f02 within f01 thus:
f01 <- function(...){
f02(b = 2,...)
}
Result:
f01(a=1)
$b
[1] 2
$a
[1] 1
This works regardless of the number of arguments in the ellipsis:
f01(a=1,c=3)
$b
[1] 2
$a
[1] 1
$c
[1] 3
Passing an ellipsis to another variadic function
You can't, you can only pass the arguments as a va_list
. See the comp.lang.c FAQ.
In general, if you're writing variadic functions (that is, functions which take a variable number of arguments) in C, you should write two versions of each function: one which takes an ellipsis (...
), and one which takes a va_list
. The version taking an ellipsis should call va_start
, call the version taking a va_list
, call va_end
, and return. There's no need for code duplication between the two versions of the function, since one calls the other.
R ellipsis - further arguments passed to or from other methods
The ellipsis argument allows one to pass arguments to a downstream function. We'll illustrate with a simple R function as follows.
testfunc <- function(aFunction,x,...) {
aFunction(x,...)
}
aVector <- c(1,3,5,NA,7,9,11,32)
# returns NA because aVector contains NA values
testfunc(mean,aVector)
# use ellipsis in testfunc to pass na.rm=TRUE to mean()
testfunc(mean,aVector,na.rm=TRUE)
...and the output:
> testfunc <- function(aFunction,x,...) {
+ aFunction(x,...)
+ }
> aVector <- c(1,3,5,NA,7,9,11,32)
>
> # returns NA because aVector contains NA values
> testfunc(mean,aVector)
[1] NA
> # use ellipsis in testfunc to pass na.rm=TRUE to mean()
> testfunc(mean,aVector,na.rm=TRUE)
[1] 9.714286
R - How to handle the dot-dot-dot (ellipis/ ... ) with multiple subsequent functions - i.e. passing only some of the variables
The solution I came up with is not very elegant but it works.
second_2<- function(abc, extras){
a<-extras[[1]]
print(abc)
print(a)
}
third_2<- function(abc, extras){
a<-extras[[2]]
print(abc)
print(a)
}
extras<-list()
extras[[1]]<-'something special'
extras[[2]]<-"non-default"
extras
first("test",second=second_2, third=third_2, extras)
surprisingly also the following code works, but with a slightly different outcome
first("test",second=second, third=third, extras)
after all, setting default values is now a little clumsy but not infeasible.
What does passing an ellipsis (...) as an argument mean in R?
The typical use of ...
argument is when a function say f
internally calls a function g
and uses ...
to pass arguments to g
without explicitly listing all those arguments as its own formal arguments. One may want to do this, for example, when g
has a lot of optional arguments that may or may not be needed by the user in the function f. Then instead of adding all those optional arguments to f
and increasing complexity, one may simply use ...
.
What it means, as you asked, is the function f
will simply ignore these and pass them on to g
. The interesting thing is that ...
may even have arguments that g
does not want and it will ignore them too, for say h
if it needed to use ...
too. But also see this so post for a detailed discussion.
For example consider:
f <- function (x, y, ...) {
# do something with x
# do something with y
g(...) # g will use what it needs
h(...) # h will use that it needs
# do more stuff and exit
}
Also, see here in the intro-R manual for an example using par
.
Also, this post shows how to unpack the ...
if one was writing a function that made use of it.
Using multiple three dot ellipsis in R
OPTION 1
Function
test = function(x = rnorm(20), y = rnorm(20), plot_options = NA, ...){
if (is.na(plot_options) == FALSE){
eval(parse(text = paste0("plot(x, y, ", plot_options, ")")))
} else {
plot(x, y, type = "n")
}
lines(x, y, ...)
}
USAGE
test()
set.seed(42)
m = rnorm(20)
n = rnorm(20)
test(x = m, y = n,
plot_options = "type = 'p', col = 'red', pch = 19, xlab = 'Test Plot', ylab = 'Y-axis'")
OPTION 2 (@Gregor's Solution)
Function
test2 = function(x = rnorm(20), y = rnorm(20), ..., line_options){
plot(x, y, ...)
if (missing(line_options)) {
lines(x, y)
} else {
do.call(lines, c(list(x = x, y = y), line_options))
}
}
USAGE
par(mfrow = c(2, 2), mar = c(2, 2, 1, 1))
test2(main = 'default')
test2(line_options = list(lty = 2), main = 'line')
test2(col = 'red', main = 'plot')
test2(col = 'red', line_options = list(lty = 2, col = 'blue'), main = 'line and plot')
pass multiple arguments to another function using template variadic function
It seems to me that the Max Langhof's solution is simple and elegant.
Unfortunately it uses template folding that is available only starting from C++17.
I propose a C++11/C++14 version that, instead template folding, uses the old trick of the initialization of an unused array
template <typename ... Args>
void Print (Type const & type, std::string const & message,
Args const & ... arg)
{
using unused = int[];
std::stringstream strstr;
strstr << message << ": ";
(void)unused { 0, (strstr << arg << ", ", 0)... };
std::string toLog = strstr.str();
// Remove last separator characters.
toLog.erase(toLog.end() - 2, toLog.end());
Log(type, strstr.str());
}
Related Topics
Writing Data Frame to PDF Table
Add an Image to a Table-Like Output in R
Changing Format of Some Axis Labels in Ggplot2 According to Condition
Overlay Grid Rather Than Draw on Top of It
Download All Files from a Folder on a Website
Extend an Irregular Sequence and Add Zeros to Missing Values
R Xml - Combining Parent and Child Nodes into Data Frame
R Subset with Condition Using %In% or ==. Which One Should Be Used
Update a Column of Nas in One Data Table with the Value from a Column in Another Data Table
Skip Some Rows in Read.CSV in R
How to Use Ggplot2's Geom_Dotplot() with Both Fill and Group
Use Rollapply and Zoo to Calculate Rolling Average of a Column of Variables