2014-04-23 14 views
5

Próbuję zrozumieć obiekt R expression, ale napotkałem pewne trudności.Dlaczego nie można ocenić tego obiektu wywołania R w wyrażeniu? (podzbiór a wyodrębnianie z obiektu wywołania)

Fragment kodu:

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

Wyniki:

#//////////////////////////////////////////////////// 
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] jest call obiekt, ale dlaczego nie można go oceniać?

Odpowiedz

11

Należy użyć operatora [[, a nie [.

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

To dlatego, że chcesz, aby wydobyć informacje z obiektu języka, a nie do jej podzbiór (zajrzeć do wnętrza 2-ej, a nie zwraca podciąg składający się z 2-ej).

Innymi słowy, podzbiorów call daje Ci call:

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

a ponieważ nie ma takiej funkcji jak a+b+1 (w rzeczywistości wynikiem oceny a+b+1 „s nie jest obiektem funkcji), R zgłasza błąd.

Co ciekawe, jeśli + zwróci obiekt funkcji, może to mieć sens:

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

Z drugiej strony, wyodrębnianie element z obiektu połączenia daje wyrażenia, które mogą być oceniane:

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

(BTW, to wyrażenie jest również wezwanie, o równowartość "+"(a, "+"(b, 1)).

EDYTUJ. Bardziej formalnie, wezwanie jest wyrazem (sekwencja) w postaci:

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

które normalnie odczytać jako:

f(a1, ..., an). 

Tak więc pierwszy element ciągu jest obiekt wykorzystywany do przekształcenia inne elementy, aby uzyskać wartość wyjściową.

tutaj x[[1]] odpowiada:

(sin, a+b+1) 

oraz, bardziej szczegółowo,

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

Zatem x[[1]][2] wykonuje podciągiem powyżej składa się z tylko 2-ej i zwrotów:

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

(tj. (a+b+1)() - brak argumentów!).Natomiast x[[1]][[2]] ekstraktów (patrzy wewnątrz) z 2-ej i daje:

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

tj a+b+1 (nutę nawiasach mniej).

EDIT2: Wszystko to jest uosobieniem piękna i ekspresji języka R, przynajmniej IMHO. Przyjrzyjmy się kolejny przykład, w którym tworzymy połączenia f1(f2(f3, f4), f3, f4), które mogą być reprezentowane przez sekwencję

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

Mamy:

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!] 

A teraz coś z zupełnie innej beczki:

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

Mam nadzieję, że to trochę wyjaśnia te problemy.

+0

Obie klasy (x [[1]] [[2]]) i klasa (x [[1]] [2]) to połączenia. – qed

+3

Jeden daje ci wezwanie do '(a + b + 1)()' a drugi do '" + "(a," + "(b, 1))'. – gagolews

+1

Wprowadziłem kilka zmian, mam nadzieję, że wyjaśnią więcej tego skomplikowanego tematu. :) – gagolews

Powiązane problemy