Frage Warum kann dieses R-Aufrufobjekt in einem Ausdruck nicht ausgewertet werden? (Subsetting vs Extrahieren von einem Call-Objekt)


Ich versuche das R zu verstehen expression Objekt, aber stieß auf einige Schwierigkeiten.

Code-Auszug:

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] ist ein call Objekt, aber warum kann es nicht ausgewertet werden?


5
2018-04-23 15:15


Ursprung


Antworten:


Du solltest das benutzen [[ Betreiber, und nicht die [.

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

Dies liegt daran, dass Sie Informationen aus dem Sprachobjekt extrahieren und nicht unterteilen möchten (schauen Sie in das zweite Element und geben Sie keine Untersequenz zurück, die aus dem zweiten Element besteht).

Mit anderen Worten, Subsetting a call gibt dir ein call:

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

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

Interessanterweise wenn + würde ein Funktionsobjekt zurückgeben, könnte dies sinnvoll sein:

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

Auf der anderen Seite gibt das Extrahieren eines Elements aus einem Aufrufobjekt einen Ausdruck, der ausgewertet werden kann:

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

(Übrigens ist dieser Ausdruck auch ein Anruf, hier gleichbedeutend mit "+"(a, "+"(b, 1)).

BEARBEITEN. Formal ist ein Aufruf ein Ausdruck (Sequenz) des Formulars:

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

was wir normalerweise lesen als:

f(a1, ..., an).

Somit ist das erste Element der Sequenz ein Objekt, das zum Transformieren der anderen Elemente verwendet wird, um einen Ausgabewert zu erhalten.

Hier x[[1]] ist äquivalent zu:

(sin, a+b+1)

oder genauer gesagt

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

So, x[[1]][2] nimmt eine Teilfolge der obigen nur aus dem zweiten Element und gibt zurück:

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

(d.h. (a+b+1)() - keine Argumente!). Andererseits x[[1]][[2]] extrahiert (schaut hinein) das 2. Element und gibt:

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

d.h. a+b+1 (Beachten Sie ein Paar Klammern weniger).

EDIT2: All dies veranschaulicht die Schönheit und Ausdruckskraft der R-Sprache, zumindest IMHO. Lassen Sie uns ein anderes Beispiel betrachten, in dem wir einen Anruf erstellen f1(f2(f3, f4), f3, f4), was durch eine Sequenz repräsentiert sein 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 auf.


11
2018-04-23 15:18