2011-12-28 13 views
6

Quale tipo di oggetto viene passato a myFunc come x? Non sembra essere un'espressione, né una funzione e lo basta solo valutarlo. Capisco che posso usare force() per valutare. Mi chiedo se c'è un modo per raccogliere più informazioni su x senza valutarlo.R - Rilevamento di espressioni

myFunc = function(x) 
{ 
    is.expression(x)  
    is.function(x) 
    str(x) 
} 
myFunc({ x = 5; print(x + 1) }) 
+1

Che dire della classe (x) – Benjamin

+0

non sembra segnalare come espressione. né type() né mode() – SFun28

+0

penso che potresti essere confuso tra espressioni (che sono fondamentalmente liste di chiamate non valutate) e i risultati di un'espressione. 'x' nella tua funzione è 6. – hadley

risposta

6

È possibile utilizzare match.call per estrarre gli argomenti:

myFunc <- function(x) { 
    x <- match.call()$x 
    print(class(x)) 
    print(typeof(x)) 
    print(mode(x)) 
    print(storage.mode(x)) 
    print(is.expression(x)) 
    print(is.call(x)) 
    if (is.call(x)) print(x[[1]]) 
} 
myFunc({x = 5; print("a")}) 
myFunc(expression(x)) 
x <- factor(1) 
myFunc(x) 
myFunc(1) 

Probabilmente ho bisogno di dire che { è una funzione di R, quindi {...} non è altro che call.

Aggiornato: il motivo per cui non è xfunction mentre { è function:

f <- function(x) { 
    x <- match.call()$x 
    print(eval(x[[1]])) 
    print(is.function(eval(x[[1]]))) 
} 

f({1}) 
+0

grazie per averlo messo insieme! Se {è una funzione, allora perché.function (x) restituisce FALSE? C'è un modo per cambiare l'ambiente di x? – SFun28

+0

perché x è 'call', non' function'. 'Call' consiste di' function' e 'arguments'. Vedi anche update. – kohske

2

Penso class farebbe il trucco ... Vedere docs.

EDIT: Secondo il docs,

per {, il risultato dell'ultima espressione valutata

Il che significa che la classe è la classe risultante dalla valutazione, che è il motivo per cui non è mostrando come "espressione". Viene passato dopo la valutazione.

+0

Hmmm,' class' restituisce 'numerico' che mi fa pensare che valuti l'espressione prima di testarlo ... – nico

+0

In realtà, anche se provi ad assegnare quell'espressione a una variabile, il espressione viene immediatamente eseguita e si finisce con una variabile numerica contenente 6 ... – nico

+0

Esattamente. La valutazione viene eseguita immediatamente, prima dell'assegnazione o passando il risultato a una funzione. – Benjamin

1

Dason appena pubblicato una risposta simile a questo su Talkstats.com per determinare se un oggetto è un frame di dati o un elenco (click here for a link to that post). Ho appena esteso ad un'espressione che credo si adatta alle vostre esigenze.

j.list <- function(list, by = NULL){ 
    print("list") 
    print(list) 
} 

j.data.frame <- function(df, ..., by = NULL){ 
    print("data frame") 
    print(df) 
} 


j.expression <- function(expression, by = NULL){ 
    print("expression") 
    print(expression) 
} 

j <- function(x, ...){ 
    UseMethod("j") 
} 

j(list(test = "this is a list")) 
j(data.frame(test = 1:10)) 
j(expression(1+ 0:9)) 
+0

j ({x = 5; print (x + 1)}) genera errore "nessun metodo applicabile per 'j' applicato all'oggetto di classe" c ('double', 'numerico') "ma la soluzione sembrava intelligente =) – SFun28

+0

Non era necessariamente per determinare se qualcosa fosse un frame di dati o un elenco - era di adattare la chiamata di funzione a se l'argomento era un frame di dati o un elenco poiché il poster voleva essere in grado di offrire funzionalità simili per entrambi i casi ma volevo che la funzione dicesse se l'oggetto passato era una lista o un frame di dati, ma grazie per lo shootout – Dason