2015-03-10 24 views
9

Czy istnieje sposób wygenerowania ostrzeżenia (i niepowodzenia ..), jeśli zmienna globalna jest używana w ramach funkcji R? Myślę, że to dużo oszczędza i zapobiega niezamierzonym zachowaniom ... np.Scalanie R: blokowanie zmiennych globalnych w funkcji

sUm <- 10 
sum <- function(x,y){ 
sum = x+y 
return(sUm) 
} 

ze względu na „typo” w zamian funkcja zawsze zwraca 10. Zamiast zwracania wartości sUm powinno się nie powieść.

+2

Zobacz: [to pytanie] (http://stackoverflow.com/questions/25373447/how-to-detect-free-variable-names-in-r-functions) lub [to pytanie] (http: // stackoverflow.com/questions/21245850/making-sure-a-function-does-not-use-a-global-variable) lub [to pytanie] (http://stackoverflow.com/questions/6216968/r-force- local-scope) do dalszej dyskusji. – MrFlick

Odpowiedz

6

Moja druga odpowiedź jest bardziej o tym, co podejście może wziąć wewnątrz swojej funkcji. Teraz przedstawię wgląd w to, co zrobić po zdefiniowaniu twojej funkcji.

Aby upewnić się, że funkcja nie korzysta ze zmiennych globalnych, gdy nie powinna, należy użyć pakietu codetools.

library(codetools) 

sUm <- 10 
f <- function(x, y) { 
    sum = x + y 
    return(sUm) 
} 

checkUsage(f) 

to wypisze komunikat:

<anonymous> local variable ‘sum’ assigned but may not be used (:1)

aby sprawdzić, czy zmienne globalne były wykorzystywane w funkcji, można porównać wyjście funkcji findGlobals() ze zmiennymi w środowisku globalnym.

> findGlobals(f) 
[1] "{" "+" "=" "return" "sUm" 

> intersect(findGlobals(f), ls(envir=.GlobalEnv)) 
[1] "sUm" 

, który mówi, że zmienna globalna sUm użyto wewnątrz f() kiedy to chyba nie powinno być.

+0

to jest niezły! łatwy sposób sprawdzenia, czy zmienne globalne są fałszywie używane w funkcji. Nie wiedziałem o tym pakiecie. Dzięki! – Jonas

+0

@ Jonas: Cieszę się, że mogłem pomóc. –

3

Korzystanie get to sposób:

sUm <- 10 
sum <- function(x,y){ 
    sum <- x+y 
    #with inherits = FALSE below the variable is only searched 
    #in the specified environment in the envir argument below 
    get('sUm', envir = environment(), inherits=FALSE) 
} 

wyjściowa:

> sum(1,6) 
Error in get("sUm", envir = environment(), inherits = FALSE) : 
    object 'sUm' not found 

Mając prawo sum w funkcji get nadal patrzeć tylko wewnątrz środowiska danej funkcji dla zmiennej, co oznacza, że ​​jeśli istnieje były dwie zmienne, jedna w funkcji i jedna w globalnym środowisku o tej samej nazwie, funkcja zawsze szukała zmiennej wewnątrz środowiska funkcji, a nigdy w środowisku globalnym:

sum <- 10 
sum2 <- function(x,y){ 
    sum <- x+y 
    get('sum', envir = environment(), inherits=FALSE) 
} 

> sum2(1,7) 
[1] 8 
3

Możesz sprawdzić, czy nazwa zmiennej pojawia się na liście zmiennych globalnych. Zauważ, że jest to niedoskonałe, jeśli dana zmienna globalna ma taką samą nazwę jak argument do twojej funkcji.

if (deparse(substitute(var)) %in% ls(envir=.GlobalEnv)) 
    stop("Do not use a global variable!") 

Funkcja stop() wstrzyma realizację funkcji i wyświetlić dany komunikat o błędzie.

5

Nie ma sposobu, aby trwale zmienić sposób rozwiązywania zmiennych, ponieważ spowodowałoby to złamanie wielu funkcji. Zachowanie, którego nie lubisz, jest bardzo przydatne w wielu przypadkach.

Jeśli zmienna nie zostanie znaleziona w funkcji, R sprawdzi środowisko, w którym funkcja została zdefiniowana dla takiej zmiennej. Możesz zmienić to środowisko za pomocą funkcji environment(). Na przykład

environment(sum) <- baseenv() 
sum(4,5) 
# Error in sum(4, 5) : object 'sUm' not found 

To działa, ponieważ baseenv() punktów do „bazowego” środowiska, który jest pusty. Należy jednak pamiętać, że nie ma dostępu do innych funkcji przy użyciu tej metody

myfun<-function(x,y) {x+y} 
sum <- function(x,y){sum = myfun(x+y); return(sUm)} 

environment(sum)<-baseenv() 
sum(4,5) 
# Error in sum(4, 5) : could not find function "myfun" 

ponieważ w języku funkcjonalne, takie jak R, funkcje są tylko zwykłe zmienne, które są również lunetą w środowisku, w którym są zdefiniowane i nie byłby dostępny w środowisku podstawowym.

Użytkownik ręcznie musiałby zmienić środowisko dla każdej zapisywanej funkcji. Ponownie, nie ma możliwości zmiany tego domyślnego zachowania, ponieważ wiele podstawowych funkcji i funkcji R zdefiniowanych w pakietach polega na tym zachowaniu.

+0

Co powiesz na funkcję tworzenia funkcji, która zrobiłaby to za Ciebie? –

+1

Cóż, nadal masz problem, że nie jest łatwo odróżnić "zmienną" od "funkcji" w R. Aby być użytecznym, prawdopodobnie będziesz chciał uzyskać dostęp do wszystkich funkcji w przestrzeni nazw. ale czasami możesz chcieć pisać funkcje, które zwracają inne funkcje. Nie jest dla mnie oczywiste, jak będzie wyglądać odpowiednie opakowanie. – MrFlick

2

Innym sposobem (lub style) jest, aby wszystkie zmienne globalne w specjalnym środowisku:

with(globals <- new.env(), { 
    # here define all "global variables" 
    sUm <- 10 
    mEan <- 5 
}) 

# or add a variable by using $ 
globals$another_one <- 42 

Następnie funkcja nie będzie w stanie je zdobyć:

sum <- function(x,y){ 
    sum = x+y 
    return(sUm) 
} 

sum(1,2) 
# Error in sum(1, 2) : object 'sUm' not found 

ale można zawsze używaj ich z globaliami $:

Aby zarządzać dyscypliną, możesz sprawdzić, czy istnieje globalny v ariable (z wyjątkiem funkcji) poza globals:

setdiff(ls(), union(lsf.str(), "globals")))