2013-01-18 40 views
12

Come parte di una funzione, voglio generare un elenco di tutti gli argomenti e i relativi valori, inclusi i valori predefiniti. Ad esempio, una funzione con questi argomenti:match.call con argomenti predefiniti

foo <- function(x=NULL,y=NULL,z=2) { 
    #formals() 
    #as.list(match.call())[-1] 
    #some other function?.... 
} 

Per dare emesso come:

> foo(x=4) 

$x 
[1] 4 

$y 
NULL 

$z 
[1] 2 

formals non aggiorna invia i valori degli argomenti valori quando viene chiamata la funzione. match.call, ma non fornisce i valori predefiniti degli argomenti. Esiste un'altra funzione là fuori che fornirà l'output come voglio?

risposta

23

Speriamo che questo non porta a draghi.

foo <- function(x=NULL,y=NULL,z=2) { 
    mget(names(formals()),sys.frame(sys.nframe())) 

} 

foo(x=4) 

$x 
[1] 4 

$y 
NULL 

$z 
[1] 2 

print(foo(x=4)) 

$x 
[1] 4 

$y 
NULL 

$z 
[1] 2 
11

è possibile utilizzare un mix di 2, match.call e formals

foo <- function(x=NULL,y=NULL,z=2) 
{ 
    ll <- as.list(match.call())[-1]  ## 
    myfor <- formals(foo)    ## formals with default arguments 
    for (v in names(myfor)){ 
      if (!(v %in% names(ll))) 
       ll <- append(ll,myfor[v]) ## if arg is missing I add it 
      } 
    ll 
} 

Ad esempio:

foo(y=2) 
$y 
[1] 2 

$x 
NULL 

$z 
[1] 2 

> foo(y=2,x=1) 
$x 
[1] 1 

$y 
[1] 2 

$z 
[1] 2 
4
foo <- function(x=NULL,y=NULL,z=2) { 
    X <- list(x,y,z); names(X) <- names(formals()); X 
} 
z <- foo(4) 
z 
#------ 
$x 
[1] 4 

$y 
NULL 

$z 
[1] 4 
+0

Umm, sembra che ci sia un errore di battitura, suppongo che dovrebbe essere 'x <- list (x, y, z)'. Se crei l'elenco manualmente, perché non nominare direttamente le voci? – Roland

+0

Risolto il problema di battitura. La domanda dovrebbe essere indirizzata all'OP. –

3

Ecco un tentativo di avvolgere questa logica in una funzione riutilizzabile a cadere nel posto di match.call:

match.call.defaults <- function(...) { 
    call <- evalq(match.call(expand.dots = FALSE), parent.frame(1)) 
    formals <- evalq(formals(), parent.frame(1)) 

    for(i in setdiff(names(formals), names(call))) 
    call[i] <- list(formals[[i]]) 


    match.call(sys.function(sys.parent()), call) 
} 

sembra che funziona:

foo <- function(x=NULL,y=NULL,z=2,...) { 
    match.call.defaults() 
} 


> foo(nugan='hand', x=4) 
foo(x = 4, y = NULL, z = 2, ... = pairlist(nugan = "hand")) 
Problemi correlati