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 and offset are evaluated in the same way as variables in formula, that is first in data and then in the environment of formula.

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.