Use of variable arguments (dot-dot-dot) in stats::lm in R [duplicate]
I can't think of a work-around as safe and as succinct as do.call
. I can explain what's going on, having debugged into the lm
call.
In the body of lm
, you'll find the statement
mf <- eval(mf, parent.frame())
On the right hand side of the assignment, mf
is the call
stats::model.frame(formula = formula, data = data, weights = ..1,
drop.unused.levels = TRUE)
and parent.frame()
is the frame of the outer_function
call (in other words, the evaluation environment of outer_function
). eval
is evaluating mf
in parent.frame()
. Due to S3 dispatch, what is ultimately evaluated in parent.frame()
is the call
stats::model.frame.default(formula = formula, data = data, weights = ..1,
drop.unused.levels = TRUE)
In the body of model.frame.default
, you'll find the statement
extras <- eval(extras, data, env)
On the right hand side of this assignment, extras
is the call
list(weights = ..1)
specifying the arguments from mf
matched to the formal argument ...
of model.frame.default
(just weights
, in this case, because model.frame.default
has formal arguments named formula
, data
, and drop.unused.levels
); data
is the data frame containing your simulated data; and env
is your global environment. (env
is defined earlier in the body of model.frame.default
as environment(formula)
, which is indeed your global environment, because that is where you defined formula
.)
eval
is evaluating extras
in data
with env
as an enclosure. An error is thrown here, because the data frame data
and your global environment env
are not valid contexts for ..n
. The symbol ..1
is valid only in the frame of a function with ...
as a formal argument.
You might have deduced the issue from ?lm
, which notes:
All of
weights
,subset
andoffset
are evaluated in the same way as variables informula
, that is first indata
and then in the environment offormula
.
There is no problem when weights
is given the value of a constant (i.e., not the name of a variable bound in an environment and not a function call) in the outer_function
call, because in that situation match.call
does not substitute the symbol ..n
. Hence
outer_function(formula = formula, data = data, weights = 5)
works (well, a different error is thrown), but
weights <- 5
outer_function(formula = formula, data = data, weights = weights)
and
outer_function(formula = formula, data = data, weights = rep(1, 100))
don't.