2009-07-23 13 views
30

Często piszę funkcje, które muszą widzieć inne obiekty w moim środowisku. Na przykład:Pisanie funkcji w R, mając na uwadze ustalanie zakresu

> a <- 3 
> b <- 3 
> x <- 1:5 
> fn1 <- function(x,a,b) a+b+x 
> fn2 <- function(x) a+b+x 
> fn1(x,a,b) 
[1] 7 8 9 10 11 
> fn2(x) 
[1] 7 8 9 10 11 

Zgodnie z oczekiwaniami, obie te funkcje są identyczne, ponieważ fn2 „widzi” a i b, gdy wykonuje. Ale gdy tylko zacznę to wykorzystywać, w ciągu około 30 minut kończę wywoływanie funkcji bez jednej z niezbędnych zmiennych (np. A lub b). Jeśli nie wykorzystam tego, to czuję, że niepotrzebnie omijam przedmioty.

Czy lepiej sprecyzować, czego wymaga funkcja? Czy też powinno to być załatwione za pomocą wstawionych komentarzy lub innej dokumentacji funkcji? Czy istnieje lepszy sposób?

Odpowiedz

36

Jeśli wiem, że będę potrzebował funkcji parametryzowane przez niektórych wartości i wielokrotnie nazwie unikam globalnych za pomocą Zamknięcie:

make.fn2 <- function(a, b) { 
    fn2 <- function(x) { 
     return(x + a + b) 
    } 
    return(fn2) 
} 

a <- 2; b <- 3 
fn2.1 <- make.fn2(a, b) 
fn2.1(3) # 8 
fn2.1(4) # 9 

a <- 4 
fn2.2 <- make.fn2(a, b) 
fn2.2(3) # 10 
fn2.1(3) # 8 

Ten starannie unika odwoływania się do zmiennych globalnych, zamiast korzystania z załączając środowisko funkcji dla aib. Modyfikacja globów aib nie prowadzi do niezamierzonych efektów ubocznych, gdy wywoływane są instancje fn2.

3

Czy problem występuje, gdy używasz zmiennej globalnej w funkcji lub przy próbie przypisania zmiennej? Jeśli to drugie podejrzewam, że to dlatego, że nie używasz <<- jako zadania w ramach funkcji. I podczas korzystania z <<- wydaje się ciemną stroną 1 może bardzo dobrze działać dla twoich celów. Jeśli jest to pierwsze, funkcja prawdopodobnie maskuje zmienną globalną.

Nazwanie zmiennych globalnych w taki sposób, że trudno byłoby je zamaskować lokalnie, może pomóc. np .: global.pimultiples <- 1:4*pi

8

Jest jeden powód, dla którego niektóre języki nie dopuszczają zmiennych globalnych: mogą łatwo doprowadzić do zepsutego kodu.

Reguły skalowania w R umożliwiają pisanie kodu w leniwy sposób - pozwalając funkcjom używać zmiennych w innych środowiskach, co pozwala zaoszczędzić trochę pisania i świetnie nadaje się do zabawy w prostych przypadkach.

Jeśli jednak robisz coś zdumiewająco skomplikowanego, to polecam przekazać funkcję wszystkich potrzebnych zmiennych (lub przynajmniej przeprowadzić gruntowne sprawdzanie poprawności w celu zastosowania opcji zastępczej w przypadku zmiennych istnieć).

W powyższym przykładzie:

Najlepszą praktyką jest stosowanie FN1.

Ewentualnie spróbuj coś

fn3 <- function(x) 
    { 
     if(!exists("a", envir=.GlobalEnv)) 
     { 
     warning("Variable 'a' does not exist in the global environment") 
     a <- 1 
     } 

     if(!exists("b", envir=.GlobalEnv)) 
     { 
     warning("Variable 'b' does not exist in the global environment") 
     b <- 2 
     } 

     x + a + b 
    } 
0

Wykorzystanie zmiennych globalnych jest ogólnie zniechęca w większości języków, a R nie jest wyjątkiem. Bardzo często krótka funkcja wykorzystuje krótkie i ogólne nazwy zmiennych, które mogą być zapełniane w środowisku globalnym. Najbezpieczniej jest a) uwzględnić wszystkie zmienne w definicji funkcji b) , a nie, aby przypisać wartości domyślne. Np. Napisz f = funkcja (a, b), raczej f = funkcja (a = 0, b = NA).