2011-01-12 5 views
5

Oto mała zagadka dla tych, którzy biegle posługują się niuansami tego, jak oceniający R obsługuje wywołania funkcji. Załóżmy, że chcę napisać funkcję, która pobiera instrukcję R, tak samo jak to, co piszę w wierszu poleceń, i powtarza zarówno ją, jak i oceniany wynik. Przykład:Argumenty polecenia Verbatim: deparse (zamiennik (foo)) w opakowaniu

> p.eval(sum(1:3)) 
sum(1:3) --> 6 

To proste; oto definicja p.eval():

p.eval <- function(v,prefix="--> ") { 
    cmd <- deparse(substitute(v)); cat(cmd,prefix,v,"\n") 
} 

Załóżmy jednak teraz chcę napisać otoki wokół p.eval, powoływać się w ten sam sposób; być może jako nieco obłąkany binarnego operatora z manekina drugi argument:

%PE% <- function(x,...) p.eval(x) 

chciałbym powołać się go tak: sum(1:3) %PE% 0 powinny być równoważne do starego p.eval(sum(1:3)). To oczywiście nie działa, ponieważ deparse(substitute()) z p.eval() daje teraz x.

Pytanie do oświeconego: czy istnieje sposób, aby to działało tak, jak chcę? Dla tego konkretnego zastosowania, jestem całkiem w porządku z definiowaniem %PE% przez kopiowanie/wklejanie definicji jednej linijki p.eval, więc to Pytanie ma głównie charakter akademicki. Może dowiem się czegoś o Ntyty-surowości oceniającego R :)

PS: Dlaczego można znaleźć powyższe funkcje przydatne? .. Przypuśćmy, że opracuję kod analizy i wywołasz go nieinteraktywnie poprzez org-babel (z czego na pewno warto grać, jeśli jesteś użytkownikiem Org-mode i/lub użytkownikiem Emacsa). Domyślnie org-babel slurps up wyjścia, jak rzeczy są oceniane w tłumaczu. Tak więc, jeśli chcę uzyskać cokolwiek poza liczbami nieprzetworzonymi, muszę jawnie skonstruować ciągi do wydrukowania przez cat lub paste, ale kto chce to zrobić, gdy lecą one przez analizę? .. Powyższy hak pozwala po prostu dołączyć % PE% 0 po linii, która ma zostać wydrukowana, a to powoduje wyświetlenie polecenia na wyjściu org.

+1

Jeśli idziesz tą drogą, radzę czytać https://github.com/hadley/devtools/wiki/Evaluation, szczególnie "Calling from another function" section – hadley

+0

Doskonały zasób, Hadley. Czekamy na zakończenie pozostałych sekcji. –

Odpowiedz

11

Spróbuj tego:

> "%PE%" <- function(x, ...) do.call(p.eval, list(substitute(x))) 
> sum(1:3) %PE% 0 
sum(1:3) --> 6 
+0

+1 Dobra odpowiedź Gabor. –

1

też może po prostu mają p.eval powrotny "v", a następnie:

p.eval <- function(v,prefix="--> ") { 
     cmd <- deparse(substitute(v)); cat(cmd,prefix,v,"\n") ; return(v) } 
"%PE%" <- function(x, y=NULL) x 
sum(1:3) %PE% Inf 
#[1] 6 
sum(1:3) %PE% # won't accept single argument 
    r # give it anything 
#[1] 6 
Powiązane problemy