Closures. Closures sind in Ruby Codeblöcke, die an den Kontext gebunden bleiben, in dem sie definiert sind. Diese Blöcke geben ein Ergebnis zurück (notfalls halt nil) und können etwa an Methoden übergeben werden.
Nützliche Beispiele dafür ist etwa die Methode open der Klasse File aus Ruby’s Standardbibliothek. Übergibt man dieser Methode einen Block (zwischen do und end) so wird die Datei geöffnet, der Block ausgeführt und die Datei dann wieder geschlossen:
File.open('/tmp/foo.txt', 'w') do |file|
file.write("baz!")
file.write("another baz!")
end
Weitere nützliche Beispiele für diese Blöcke sind etwa Fehlerbehandlungsroutinen. Besonders elegant ist es die Blöcke mit Makros (siehe eine der nächsten DdiaRm Folgen) zu kombinieren.
Diese Codeblöcke sind in etwa das Äquivalent zu Lambdafunktionen in Sprachen, die das Lambdakalkül beherrschen. So kann man das Problem ,,erzeuge einen Akkumulator” elegant lösen. Dabei geht es darum, eine Routine zu schreiben, die einen Wert n erhält und eine Funktion zurück gibt, die einen Wert m erhält und dann die Summe n + m zurück gibt. In Ruby sieht das dann so aus (Proc Objekte sind die ,,wahre” objektorientierte Natur von Codeblöcken):
def create_accu(n)
return Proc.new { |m| n + m}
end
my_accu = create_accu(10)
puts myaccu.call(2) # gibt ,,12'' aus
In funktionalen Sprachen geht es ähnlich einfach (hier Haskell):
create_accu n = \m -> x + n
my_accu = create_accu 10
my_accu 2 -- ergibt auch ,,12''
Wer mir vormacht, wie sowas in C, Java, Python usw. ähnlich elegant geht (jaja, C++ kann das auch, wenn man den Funktionsaufrufsoperator überlädt, aber das ist nicht in der Liste, Jörg!), dem schicke ich per Email ein Eis!