2014-04-23 4 views
5

Ich versuche, das Objekt R expression zu verstehen, stieß jedoch auf einige Schwierigkeiten.Warum kann dieses R-Objekt in einem Ausdruck nicht ausgewertet werden? (Subsetting vs Extrahieren von einem Call-Objekt)

Code-Snippet:

a = 1 
b = 2 
x = expression(sin(a+b+1)) 
print(class(x[[1]][2])) 
eval(x[[1]][2]) 

Ergebnisse:

#//////////////////////////////////////////////////// 
x = expression(sin(a+b+1)) 
#//////////////////////////////////////////////////// 
print(class(x[[1]][2])) 
[1] "call" 
#//////////////////////////////////////////////////// 
x = expression(sin(a+b+1)) 
#//////////////////////////////////////////////////// 
print(class(x[[1]][2])) 
[1] "call" 
#//////////////////////////////////////////////////// 
eval(x[[1]][2]) 
Error in eval(expr, envir, enclos) : attempt to apply non-function 
2: eval(expr, envir, enclos) 
1: eval(x[[1]][2]) 

x[[1]][2] ein call Objekt ist, aber warum kann sie nicht bewertet werden?

Antwort

11

Sie sollten den Operator [[ verwenden und nicht den [.

a <- 1 
b <- 2 
eval(x[[1]][[2]]) 
## [1] 4 

Dies liegt daran, dass Sie Informationen aus dem Sprachobjekt extrahieren möchten, und es nicht zu der Teilmenge (innerhalb des zweiten Elements aussehen, und das aus dem zweiten Elemente keine Teilfolge zurück).

Mit anderen Worten, ein subsetting call gibt Ihnen ein call:

x[[1]][2] 
## (a + b + 1)() 

und weil es keine solche Funktion wie a+b+1 ist (in der Tat, die Bewertung das Ergebnis a+b+1 ‚s ist kein Funktionsobjekt), R gibt einen Fehler aus.

Interessanterweise wenn + ein Funktionsobjekt zurückkehren würde, dies Sinn machen könnte:

"+" <- function(a, b) { function() print(":-)") } 
(a+b+1)() 
[1] ":-)" 

Auf der anderen Seite, ein Element aus einem Call-Objekt zu extrahieren gibt Ihnen einen Ausdruck, der ausgewertet werden kann:

x[[1]][[2]] 
a + b + 1 

(BTW, dieser Ausdruck ist auch ein Aufruf, hier entspricht "+"(a, "+"(b, 1)).

BEARBEITEN. Formal wird ein Anruf ein Ausdruck (Sequenz) der Form:

(f, a1, ..., an), 

die wir als normal gelesen:

f(a1, ..., an). 

Somit wird das erste Element der Sequenz ist ein Ziel verwendet, um die Transformations andere Elemente, um einen Ausgabewert zu erhalten.

Hier x[[1]] entspricht:

(sin, a+b+1) 

oder, genauer,

(sin, (+, a, (+, b, 1))). 

Somit nimmt x[[1]][2] eine Subsequenz der oben aus nur der 2. Element und gibt:

((+, a, (+, b, 1))) 

(dh (a+b+1)() - keine Argumente!).Auf der anderen Seite x[[1]][[2]] Extrakte (sieht innen), um das zweite Element und gibt:

(+, a, (+, b, 1)),

heißt a+b+1 (man beachte, ein Paar Klammern weniger).

EDIT2: All dies veranschaulicht die Schönheit und Ausdruckskraft der Sprache R, zumindest IMHO. Nehmen wir ein anderes Beispiel studieren, in dem wir einen Anruf f1(f2(f3, f4), f3, f4), schaffen, die durch eine Sequenz dargestellt werden kann

(f1, (f2, f3, f4), f3, f4). 

Wir haben:

f <- function(...) invisible(NULL) 
f1 <- f; f2 <- f; f3 <- f; f4 <- f # for sake of clarity below 
expr <- quote(f1(f2(f3, f4), f3, f4)) 
print(expr) 
## f1(f2(f3, f4), f3, f4),   i.e. (f1, (f2, f3, f4), f3, f4) 
print(expr[1:3]) 
## f1(f2(f3, f4), f3),    i.e. (f1, (f2, f3, f4), f3) 
print(expr[3:4]) 
## f3(f4),       i.e. (f3, f4) 
print(expr[3]) 
## f3(),        i.e. (f3) 
expr[2] 
## f2(f3, f4)(),      i.e. ((f2, f3, f4)) [subsetting!] 

Und jetzt etwas ganz anderes:

expr[[2]] 
## f2(f3, f4),      i.e. (f2, f3, f4) [extraction] 

Hoffe das klärt diese Fragen ein wenig.

+0

Beide Klassen (x [[1]] [[2]]) und Klasse (x [[1]] [2]) sind Aufrufe. – qed

+3

Man gibt Ihnen einen Aufruf an '(a + b + 1)()' und den anderen an '" + "(a," + "(b, 1))'. – gagolews

+1

Ich habe einige Änderungen vorgenommen, hoffe, dass es mehr über dieses komplizierte Thema klärt. :) – gagolews

Verwandte Themen