Ein kurzer Blick auf Closures

von Karl-Kuno Kunze

Erste Hilfe zu Closures finden Sie hier!

In diesem Artikel stelle ich das Konzept einer Closure vor. Zunächst motivieren wir, warum es manchmal hilfreich sein kann, sich damit auszukennen. Dann führen wir das Konzept der Umgebung ein und schließlich bauen wir damit eine Closure.

Sicher ist Ihnen die Fehlermeldung Objekt des Typs ‚closure‘ ist nicht indizierbar schon mal irgendwo begegnet. Um zu verstehen, was R damit sagen will, sollte man das Konzept der Closure verstehen. In einem Satz: Eine Closure ist eine Funktion zusammen mit einer Umgebung (environment).

Schauen wir uns also zunächst Umgebungen an und verbinden dann Umgebungen und Funktionen. Das ist alles, was wir für eine Closure brauchen.

Environment

Stellen Sie sich eine Umgebung vor wie einen Container, der Objekte enthält. So, wie alles ein Objekt in R ist, kann man das von einer Umgebung auch sagen. Zunächst erzeugen wir zwei Umgebungen und spielen anschließend etwas damit herum:

env1 <- new.env()
env2 <- new.env()
env1[["iAm"]] <-"Environment 1"  # Eine Möglichkeit, Objekte in Umgebungen zu erzeugen
env2$iAm <- "Environment 2"      # Eine andere Möglichkeit
get("iAm", envir = env1)         # Eine Möglichkeit, auf Objekte in Umgebungen zuzugreifen
## [1] "Environment 1"
env2$iAm                         # Eine andere Möglichkeit
## [1] "Environment 2"

Sie können mit verschiedenen Funktionen auf Objekte in Umgebungen zugreifen und sie verändern. Dazu gehören: with(), within() and attach().

Jede Umgebung lebt in einer Eltern-Umgebung. Mit anderen Worten: Jede Umgebung ist ein Objekt, welches in einer ‚darüber‘ liegenden Umgebung definiert ist.

parent.env(env1)
## <environment: R_GlobalEnv>

Closure

Jetzt definieren wir eine Funktion, die den Inhalt des Objekts iAm ausgibt. Implizit verbinden wir mit dieser Funktion die globale Umgebung und haben unsere erste Closure erstellt:

iAm <- "R_GlobalEnv"
envFun <- function() cat("I belong to :", iAm)
envFun()
## I belong to : R_GlobalEnv

Jetzt verbinden wir mit derselben Funktion die Umgebung env1 und haben eine andere Closure erstellt:

environment(envFun) <- env1
envFun()
## I belong to : Environment 1

Jetzt verbinden wir noch eine andere Umgebung, nämlich env2, mit der Funktion und haben wieder eine andere Closure erstellt:

environment(envFun) <- env2
envFun()
## I belong to : Environment 2

Die globale Umgebung weisen wir der Funktion wie folgt zu:

environment(envFun) <- .GlobalEnv
envFun()
## I belong to : R_GlobalEnv

Wenn Sie also R frisch starten und eine Funktion erzeugen, wird diese zusammen mit der globalen Umgebung eine Closure bilden.

Lassen Sie uns die Fehlermeldung von oben noch einmal provozieren. Das machen wir so:

envFun[]
## Error in envFun[]: Object des Typs 'Closure' ist nicht indizierbar

Sie können Funktionen nicht indizieren (oder Teilmengen bilden). Das ist nicht wirklich überraschend!

________________________________________________________________________________________________

Sie sind an weiteren Tipps über die Programmiersprache R interessiert? Tragen Sie sich in unseren Newsletter ein und bleiben Sie auf dem Laufenden.

Interesse an einem Seminar beim Autor Karl-Kuno Kunze? Hier gelangen Sie zu unseren Trainings in Potsdam. Optional auch in Ihrem Unternehmen vor Ort. Sprechen Sie uns an!