call default args
mschubert opened this issue · comments
In io/text
: the .set_defaults
function should be moved to be generally accessible, as matching default args in a call is a task that will occur more often (I'm working on something now, for instance).
.set_defaults = function (call, .formals = formals(sys.function(sys.parent()))) {
for (n in names(.formals))
if (n != '...' && ! (n %in% names(call)))
call[[n]] = .formals[[n]]
call
}
The method also fails for functions with NULL
arguments, like the one below.
x = function(y=NULL) {
args = .set_defaults(match.call())
as.list(args)
}
# > x()
# Error in call[[n]] = .formals[[n]] : subscript out of bounds
@klmr any chance to get this done.. err.. today?
I’m on it, as I agree.
some preliminary code to consider that does what I need (basically, just match.call()
with defaults):
match_call_defaults = function (call = match.call(sys.function(sys.parent())),
.formals = formals(sys.function(sys.parent()))) {
call = as.list(call)[-1]
.formals = .formals[names(.formals) != '...']
for (n in names(call))
.formals[[n]] = call[[n]]
.formals
}
I was going to suggest something very similar.
Err, scratch that, your function does something else entirely. My function returns a call
object that can be eval
’d. Yours doesn’t. I’m not exactly sure which purpose your function vs. mine should fulfill.
Yes, the two are semantically different but structurally similar. Mine should get all arguments of the function call (including default arguments) as a list.
Ah, shame: I’d tried using a loop-less code:
match_call_defaults = function (call = match.call(sys.function(sys.parent()), sys.call(sys.parent())),
.formals = formals(sys.function(sys.parent()))) {
.formals = .formals[names(.formals) != '...']
new_call = as.call(c(call[[1]], .formals))
new_call[names(call[-1])] = call[-1]
new_call
}
But this fails to expand ...
in the call. So:
(function (...) match_call_defaults())(1, 2, 3)
ends up with an empty argument list.