2014-04-26 6 views
5

Ich bin ziemlich neu in R, komme aber von Scheme - das auch lexikalisch begrenzt ist und Verschlüsse hat -, dass ich in der Lage wäre, äußere Variablen in einem Abschluss zu mutieren.Eine Variable in einem Abschluss mutieren

ZB in

foo <- function() { 
    s <- 100 

    add <- function() { 
    s <- s + 1 
    } 

    add() 
    s 
} 

cat(foo(), "\n") # prints 100 and not 101 

Ich würde foo() erwarten 101 zurück, aber es gibt tatsächlich 100:

$ Rscript foo.R 
100 

Ich weiß, dass Python das global Schlüsselwort hat Umfang von Variablen zu deklarieren (doesn arbeite aber nicht mit diesem Beispiel. Braucht R etwas Ähnliches?

Was mache ich falsch?

aktualisieren

Ah, ist das Problem, dass ich in add einen neuen, lokalen Variable s, die das äußerte s Schatten erschaffe? Wenn ja, wie kann ich s mutieren, ohne eine lokale Variable zu erstellen?

+0

Moderatoren können als Duplikate schließen, oder Sie können mitmachen und für die Schließung einer Mitgliedschaft stimmen. –

+0

@BondedDust Gotcha, ich habe dafür gestimmt, dass auch geschlossen wird. Hatte nur Probleme damit zu googeln --- Ich habe die Lösung erst gefunden, als ich hier gepostet habe. So können andere Mods entscheiden, was damit zu tun ist. – csl

+1

Zwei weitere Stimmen und es wird geschlossen, unabhängig von der Aufmerksamkeit des Moderators. Möglicherweise stellen Sie fest, dass die Funktion Reference Classes ein Paradigma ist, das zu Ihrem Programmierstil passt und bei normalen R-Anwendungen nicht als gefährlich angesehen wird. Es verwendet benannte Umgebungen und lässt Sie einige der Eigenschaften von "globalen" Variablen haben. –

Antwort

3

Verwenden Sie den Operator <<- für die Zuweisung in der add()-Funktion.

Von ?"<<-":

Die Betreiber <<- und ->> werden in der Regel nur in Funktionen verwendet und verursachen eine Suche gemacht durch übergeordnete Umgebungen für eine bestehende Definition der Variablen zugewiesen wird. Wenn eine solche Variable gefunden wird (und ihre Bindung nicht gesperrt ist), wird ihr Wert neu definiert, andernfalls erfolgt die Zuweisung in der globalen Umgebung. Beachten Sie, dass sich ihre Semantik von der in der S-Sprache unterscheidet, aber in Verbindung mit den Scoping-Regeln von R nützlich ist. Weitere Einzelheiten und Beispiele finden Sie im Handbuch "R-Definition".

+0

Sie sagen "zur Zuweisung". Soll ich 'immer' '' '' für die Zuweisung verwenden? Verwenden Sie nur '<-' für Deklarationen? – csl

+1

Nur wenn Sie auf einen außerhalb der Funktion bindenden Namen zugreifen möchten (informell). Ansonsten solltest du es überhaupt nicht benutzen: es ist ziemlich "gefährlich". – gagolews

+0

Es besagt, dass '<< -' in der _global_-Umgebung zugewiesen wird, wenn keine Referenzen gefunden werden können, die in die übergeordneten Umgebungen gehen. Das klingt für mich beängstigend, ich würde erwarten, dass es stattdessen _local_ definiert. Ist das ein Problem? – csl

3

Sie auch assign nutzen können und den Umfang genau das envir Argument definieren, funktioniert auf die gleiche Art und Weise wie <<- in Ihrer add Funktion in diesem Fall aber macht Ihre Absicht, ein wenig mehr klar:

foo <- function() { 
    s <- 100 

    add <- function() { 
    assign("s", s + 1, envir = parent.frame()) 
    } 

    add() 
    s 
} 

cat(foo(), "\n") 

Natürlich ist der bessere Weg für diese Art von Sache in R, dass Ihre Funktion die Variable (oder Variablen) zurückgibt, die sie modifiziert und der ursprünglichen Variablen explizit zuweist:

foo <- function() { 
    s <- 100 
    add <- function(x) x + 1 
    s <- add(s) 
    s 
} 

cat(foo(), "\n") 
2

Hier ist ein weiterer Ansatz, der ein wenig sicherer als die assign oder <<- Ansätze sein können:

foo <- function() { 
    e <- environment() 
    s <- 100 

    add <- function() { 
     e$s <- e$s + 1 
    } 

    add() 
    s 
} 

foo() 

Die <<- Zuordnungsprobleme verursachen kann, wenn Sie versehentlich Ihre Variablennamen falsch schreiben, wird es noch etwas tun, aber Es wird nicht das sein, was Sie erwarten, und es kann schwierig sein, die Ursache des Problems zu finden. Der Ansatz assign kann schwierig sein, wenn Sie Ihre Add-Funktion dann in eine andere Funktion verschieben oder von einer anderen Funktion aufrufen möchten. Der beste Ansatz besteht darin, dass die Funktionen Variablen nicht außerhalb ihres eigenen Bereichs ändern und dass die Funktion alles zurückgibt, was wichtig ist.Wenn dies jedoch nicht möglich ist, verwendet die obige Methode lexikalisches Scoping für den Zugriff auf die Umgebung e und weist sie dann der Umgebung zu, so dass sie immer spezifisch dieser Funktion zugeordnet wird, niemals über oder unter.

Verwandte Themen