Erste Hilfe zu Closures

von Karl-Kuno Kunze

Mein Artikel über Closures ist der bei weitem am häufigsten aufgerufene. Wahrscheinlich liegt es an der Fehlermeldung Objekt des Typs 'closure' ist nicht indizierbar, die R ab und zu ausgibt. Hier ist ein dreistufiger Erste-Hilfe-Plan dazu.

Soforthilfe

Wenn Sie ganz schnell weitermachen wollen:

Ersetzen Sie in der Fehlermeldung das Wort Closure durch das Wort Funktion.

Viel Erfolg bei der Fehlersuche und bis zum nächsten Mal!

Etwas detaillierter

Wenn Sie noch einen Moment Zeit haben oder den Fehler nicht gefunden haben, schauen Sie sich an, wie wir die Fehlermeldung selbst provozieren können. Wir definieren eine Funktion und rufen diese zunächst korrekt auf, anschließend jedoch mit eckigen Klammern, was R bemängelt:

a <- function() {return(42)}
a()
## [1] 42
a[1]
## Error in a[1]: Objekt des Typs 'closure' ist nicht indizierbar

Sie behandeln a wie einen Vektor, auf dessen erstes Element Sie zugreifen wollen. Das kann nicht klappen. Entweder haben Sie aus Versehen eine Funktion verwendet oder aus Versehen eckige Klammern (also eine Methode zum Indizieren) verwendet.

Noch etwas detaillierter

R ist eine funktionale Sprache. In einer funktionalen Sprache werden Funktionen wie Bürger erster Klasse behandelt. Niemand hält Sie davon ab, eine Funktion zu definieren, die Ihrerseits wieder eine Funktion zurückgibt. Sozusagen eine Funktionsfabrik. Hier ein Beispiel:

funFactory <- function () {
  return(
    function (var) {var + 1} 
    )
}
inc <- funFactory()
inc(2)
## [1] 3

Jetzt gehen wir noch einen Schritt weiter und nähern uns endlich dem Begriff der Closure. Wandeln wir das obige Beispiel wie folgt ab:

funFactory <- function (input) {
  var <- input
  return(
    function () {var + 1} 
    )
}

Die Funktion incFactory nimmt ein Argument entgegen und weist es der Variablen var zu. Die Funktion, welche wir zurückgeben, nimmt jedoch keine Arguemnte entgegen. Sie sucht nach der Variablen in der nächst möglichen Umgebung, nämlich der von incFactory. Daher gibt die Funktion auch keinen Fehler aus, was man eigentlich erwarten würde. Die so gefundene Variable wird um eins erhöht, daher der Name inc für increment.

Jetzt weisen wir der Variablen inc2 die Funktion zu, welche incFactory zurückgibt. Die Funktion incFactory erwartet ein Argument, was wir auch übergeben.

inc2 <- funFactory(2)
inc2()
## [1] 3

Beim Aufruf der Funktion inc2 mit inc2() wird nicht etwa ein Fehler ausgegeben, sondern inc2 hat seine Umgebung aus der Fabrik einfach mitgenommen! In dieser sucht es und findet die 2, so dass sie korrekterweise 3 zurückgeben kann:

Und damit sind wir bei der Closure:

Funktion + Umgebung = Closure

In einer funktionalen Sprache lebt eine Funktion niemals allein, sondern immer zusammen mit der sie umgebenden Umgebung. Im Deutschen wird das Konzept auch als Funktionsabschluss bezeichnet.

Eine Funktion hat also immer Ihren Koffer mit Umgebungen dabei. Den packt sie aber nur ein Mal, wenn sie erzeugt wird!

Hier noch ein Test:

inc20 <- funFactory(20)
inc20()
## [1] 21

Vielleicht haben Sie jetzt auch die Nerven für den andere Artikel über Closures und Environments. Viel Spaß beim Experimentieren!

________________________________________________________________________________________________

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!

 

Titelbild: Rainer Sturm  / pixelio.de