2016-12-10 4 views
1

Ich habe den folgenden Code, um die komplexen Umgebung Schichten für das Verständnis:Funktion Umgebung in R

depositor <- function() { 
    balance <- 0 
    function(amount) { 
    balance <<- balance + amount # assign in the parent 
    return(balance) 
    } 
} 
deposit <- depositor() 
deposit(100) 
100 
deposit(32) 
132 

Können Sie mir bitte erklären, wie der obige Code in Bezug auf die Umwelt funktioniert?

Ich verstehe nicht von der Linie deposit <- depositor()

Danke Jungs!

+0

'Depositor' eine Funktion zurückgibt. Diese Funktion nimmt eine Zahl als Eingabe und speichert die kumulative Summe der bisher empfangenen Zahlen. –

+0

Dies ist eine Funktion innerhalb einer Funktion.Das Rückgabeobjekt von "depositor()" ist eine Funktion, weshalb "deposit (100)" funktioniert. Mein Rat wäre, die Quelle zu ignorieren, in der Sie dies gefunden haben, da dies nicht die "richtige" Art ist, Dinge zu tun. –

+0

Ein anderes interessantes Experiment wäre es, eine andere Funktion durch 'deposit2 <- depositor()' zu machen. Beginnt diese Funktion von 0 oder 132? –

Antwort

4

Das Schlüsselloch, dieses Beispiel zu verstehen ist depositor() Es

depositor() 

function(amount) { 
    balance <<- balance + amount # assign in the parent 
    return(balance) 
    } 
<environment: 0x8936fb0> 

Dieser Teil ist etwas einfach zurück. Der letzte vollständige Block innerhalb der äußeren Funktion depositor() ist die Definition einer anonymen Funktion function(amount). Diese Funktion wird also zum Rückgabewert der äußeren Funktion, genau wie jede gewöhnliche Variable. Der Umfang sowohl der balance als auch dieser anonymen Funktion ist auf die äußere Funktion, d. H. depositor, beschränkt, und auf sie kann von außen nicht direkt zugegriffen werden.

Die zurückgegebene anonyme Funktion kann jedoch im übergeordneten Frame (globale Umgebung) gespeichert und wiederverwendet werden.

environment(fun = depositor) 
# <environment: R_GlobalEnv> 
environment(fun = deposit) 
# <environment: 0x8a3f5a8> 
parent.env( environment(fun = deposit)) 
# <environment: R_GlobalEnv> 

deposit <- depositor() retuned speichert diese Funktion in einer Lagerstätte var genannt, und es kann durch sie noch auf die innere Funktion deposit(amountvalue)

Der Umfang der amount zugegriffen werden, beschränkt ist. Es gibt keine Möglichkeit, den Wert von amount über die äußere Funktion an ihn zu übergeben, da er nirgendwo sonst zugewiesen wird. Das kann nur durch die gespeicherte Proxy deposit(100)


Bearbeiten erfolgen: revisited ich meine Antwort und fand ich war das interessanteste Teil dieser Übung ausgelassen. Warum dauert der Wert balance von einem Anruf zum anderen? das heißt, warum setzt der nächste Anruf den Wert des Saldos nicht auf 0 zurück? Jeder neue Anruf an (nicht Anzahlung!) wird eine Funktion mit seiner eigenen übergeordneten/umschließenden Umgebung zurückgeben. Hier ist der Beweis: Es ist auch in einem Kommentar oben @Kota Mori vorgeschlagen:

deposit<- depositor() 
x<- depositor() 

#following will have two different values 
environment(deposit) 
environment(x) 
# and they will work independently 
x(100); x(20) 
deposit(100);deposit(1000) 

Dies ist der Kern von closure, ein Thema, zu dem ich etwas zu bieten haben. Ein Aufruf der inneren Funktion wird nicht in die mit dem vorherigen Aufruf verbundene Umgebung eingreifen, da die Elternfunktion selbst nicht aufgerufen wird, sondern nur die innere Funktion. In diesem Fall wird die innere Funktion aktualisiert auch Balance in ihrer jeweiligen umschließenden Umgebung durch die <<- Zuordnung, so dass der Wert von einem Anruf persistierenden zum nächsten


Eines anderen Sache sein kann, warum eine Variable aus einer Funktion zurück nicht kommen mit ähnlichem Gehäuse? Es ist, weil nach Dokumentation von function -