mschubert / ebits

R bioinformatics toolkit incubator

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.