Pisanie funkcji w R, pamiętając o zakresach
Często piszę funkcje, które muszą widzieć inne obiekty w moim środowisku. Na przykład:
> 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
może "widzieć" a i b podczas wykonywania. Ale za każdym razem, gdy zaczynam z tego korzystać, w ciągu około 30 minut kończę wołanie funkcji bez jednej z niezbędnych zmiennych(np. a lub b). Jeśli tego nie wykorzystam, to czuję się, jakbym niepotrzebnie przerzucał przedmioty.
Czy lepiej być jasno o tym, czego wymaga funkcja? A może powinno się o to zadbać poprzez wbudowane komentarze lub inną dokumentację funkcji? Jest lepszy sposób?
4 answers
Jeśli wiem, że będę potrzebował funkcji parametryzowanej przez pewne wartości i wywoływanej wielokrotnie, unikam globali używając zamknięcia:
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
Pozwala to uniknąć odwoływania się do zmiennych globalnych, zamiast tego używa środowiska zamkniętego funkcji dla a i b. modyfikacja globali a i b nie prowadzi do niezamierzonych efektów ubocznych podczas wywoływania instancji fn2.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-26 05:03:56
Istnieje powód, dla którego niektóre języki nie zezwalają na zmienne globalne: mogą łatwo prowadzić do uszkodzenia kodu.
Reguły zakresów w R pozwalają na pisanie kodu w leniwy sposób - pozwolenie funkcjom na używanie zmiennych w innych środowiskach może zaoszczędzić trochę pisania, i świetnie nadaje się do zabawy w prostych przypadkach.
Jeśli jednak robisz coś zdalnie skomplikowanego, polecam przekazać funkcję wszystkim zmiennym, których potrzebuje (lub przynajmniej mieć jakieś dokładne sprawdzenie stanu zdrowia psychicznego w miejscu, aby mieć awaryjny w przypadku, gdy zmienne nie istnieją).
W powyższym przykładzie:
Najlepszą praktyką jest stosowanie fn1.
Alternatywnie spróbuj czegoś podobnego
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
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-23 08:49:28
Czy problem pojawia się, gdy używasz zmiennej globalnej w funkcji lub gdy próbujesz przypisać zmienną? Jeśli to ta ostatnia, to podejrzewam, że to dlatego, że nie używasz <<-
jako przypisania w funkcji. I podczas używania <<-
wydaje się być ciemną stroną 1 może bardzo dobrze działać dla Twoich celów. Jeśli jest to pierwsza, funkcja prawdopodobnie maskuje zmienną globalną.
Nazywanie zmiennych globalnych w taki sposób, że trudno byłoby je zamaskować lokalnie może pomóc. np.: global.pimultiples <- 1:4*pi
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-23 05:15:11
Użycie zmiennych globalnych jest ogólnie zalecane w większości języków, A R nie jest wyjątkiem. Bardzo często funkcja short używa krótkich i ogólnych nazw zmiennych, które mogą być wypełniane w środowisku globalnym. Najbezpieczniej jest a) włączyć wszystkie zmienne w definicji funkcji B) a nie przypisać wartości domyślne. Np. napisz f=function(A,b), a raczej f = function (a = 0, B = NA).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-24 01:13:09