2014-05-22 13 views
10

Jedną z największych funkcji R jest leniwy szacunek. Prowadzi to do często spotykanego stylu, w którym można używać argumentów jako wartości innych argumentów. Na przykład, w świetnej książce Hadley na Advanced R widać this example:Lazy Ocena: Dlaczego nie mogę użyć wykresu (..., xlim = c (0,1), ylim = xlim)?

g <- function(a = 1, b = a * 2) { 
    c(a, b) 
} 
g() 
#> [1] 1 2 
g(10) 
#> [1] 10 20 

Teraz chciałbym zrobić to samo dla działki z xlim i ylim, jednak nie działa:

> plot(1, 1, ylim = c(0,1), xlim = ylim) 
Error in plot.default(1, 1, ylim = c(0, 1), xlim = ylim) : 
    object 'ylim' not found 
> plot(1, 1, xlim = c(0,1), ylim = xlim) 
Error in plot.default(1, 1, xlim = c(0, 1), ylim = xlim) : 
    object 'xlim' not found 
  • Czy ktoś wie, dlaczego?
  • Czy istnieje sposób, aby to osiągnąć?
+0

myślę, że to jest łatwe do wyjaśnienia ze zaktualizowanymi definicjami w http : //adv-r.had.co.nz/Environments.html: domyślnie a rgumenty są oceniane środowisko wykonawcze funkcji, podane argumenty są oceniane jako środowisko wywołania funkcji. – hadley

Odpowiedz

13

Quoting from the good manual:

4.3.3 ocena Argument

Jedną z najważniejszych rzeczy, które trzeba wiedzieć o ocenie argumentów do funkcji jest to, że dostarczane argumenty i domyślne argumenty są traktowane różnie. Podane argumenty funkcji są obliczane w ramce oceny wywołującej funkcji . Domyślne argumenty funkcji są obliczane w ramce oceny funkcji.

Aby zobaczyć, co to oznacza w praktyce utworzyć funkcję, w którym wartość domyślna jeden argument jest funkcją wartości kolejny argument za:

f <- function(x=4, y=x^2) { 
    y 
} 

Wywołany z y „s wartości domyślnej, R wygląda na ocenę y w ramce oceny wywołania funkcji, tjw tym samym środowisku, w którym całe ciało funkcji pobiera ocenianego - miejsce, gdzie x miał bardzo dobrze lepiej (i oczywiście robi) istnieje:

f() 
# [1] 16 

Wywołany z dostarczanej wartości z y, R wygląda w ramy oceny funkcji wywołującej (tutaj globalnym środowisku), nie znajduje x i pozwala wiedzieć, więc w jego komunikat o błędzie:

f(y=x^2) 
# Error in f(y = x^2) : object 'x' not found 
+0

Ta ostatnia linia jest całkiem interesująca. Więc nawet jeśli ustawiłeś domyślną wartość 'x' na 4, R nie znajdzie jej w ramce oceny? Oczywiście "nie", ale trochę trudno zrozumieć, dlaczego. –

+0

@RichardScriven - Tak, dlatego użyłem tego przykładu :-) Nie poczujesz się z tym komfortowo aż do momentu, kiedy naprawdę to zrozumiesz! (Dla mnie ta chwila nadeszła wiele lat po pierwszym czytaniu tego fragmentu, miejmy nadzieję, że pomoże to przyspieszyć proces dla innych!) –

+0

... która może nie być daleko, ponieważ sprawiłeś, że teraz jestem ciekawy. :) Nie miałem też pojęcia, że ​​argumenty funkcji domyślnej trafiają do środowiska globalnego. Pomyślałem, że pozostają w środowisku funkcjonalnym, a funkcja przeszła w globalne środowisko. Mam do przeczytania! –

5

Istnieje tutaj problem z zakresu. W zestawie plot(1, 1, ylim = c(0,1), xlim = ylim) nazwa ylim jest dostępna tylko jako nazwa parametru i nie jest ogólnie dostępna dla wywołującego.

Aby zmienna była używana po prawej stronie zadania, musi być dostępna w zakresie wywoływania.

Powodem Twój pierwszy przykład działa dlatego piszesz domyślne argumenty w definicji funkcji, które dokłada mieć dostęp do wszystkich parametrów.

Możliwym obejście, które ma sens tylko jeśli jest to domyślny samo chcesz w wielu przypadkach jest owinąć działka funkcję w nowej funkcji, która ma ten problem.

myplot <- function(x, y, ylim, xlim = ylim,...) { 
    plot(x,y, ylim = ylim, xlim = xlim,...) 
} 

myplot(1,1, ylim=c(0,1)) 
+0

Ale dlaczego działa w powyższym przykładzie (przepraszam, pierwszy przykład był nieprawidłowy)? – Henrik

+0

@Henrik, właśnie zaktualizowałem. Drugi scenariusz to funkcja ** call **, która jest dopasowana do kontekstu rozmówcy. Pierwszy scenariusz to funkcja ** definicja **, która jest dopasowana do kontekstu odbiorcy. – merlin2011

+0

@Henrik, również zaktualizowałem nieco słabe obejście. – merlin2011

Powiązane problemy