Dinge, die ich an Ruby mag #2: Iteratoren

Ihr größtes Anwendungsgebiet haben Closure (DdiaRm #1) in Ruby bei Iteratoren. Damit kann man sequentiell auf alle Elemente einer Kollektion wie etwa Felder oder Listen zugreifen. Dabei wird die interne Struktur gekapselt.

Ohne Iteratoren sieht der Zugriff auf Felder in Java etwa so aus:

// arr ist ein mit Integern gefülltes Feld

for (int i = 0; i ) {
  System.out.println(arr[i]);
}

In Java sieht das ganze mit Iteratoren etwa so aus:

// v ist ein Vector

for (Enumeration e = v.elements() ; e.hasMoreElements() ;) {
  System.out.println(e.nextElement());
}

In Ruby werden Blöcke benutzt, an die dann je nach Kollektionstyp die Werte übergeben werden. Zum Beispiel sieht das ganze so aus:

// arr ist ein Feld, hash eine Hashtabelle

arr.each do |element|
  puts element
end

hash.each do |key, value|
  puts "#{key}, #{value}"
end

Und es gibt dann noch ein bisschen syntaktischen Zucker, so dass man auch wie folgt über Felder iterieren kann:

for element in arr do
  puts element
end

Blöcke haben den Vorteil, dass sie z.B. auch rekursiv angewendet werden können:

def dump_tree(node, depth=0, &block)
  puts (" " * depth) + yield(node)
  for child in node.children do
    dump_tree(child, depth + 1)
  end
end

Jetzt kann ich diese Routine auf alle Instanzen von Datenstrukturen die eine children Methode bereit stellen loslassen:

dump_tree(tree) do |node|
  node.title + ", " + node.foo + ": " + node.bar
end

Rein syntaktisch sind Iteratoren mit Blöcken in Ruby meiner Meinung nach Konzepten aus der funktionalen Programmierung ähnlicher als den Iteratoren aus Java/C# usw. Statt ein zusätzliches Objekt einer speziellen Klasse zu instantiieren, kann man ähnlich wie bei Typen in Haskell, welche die Functor Klasse implementieren einfach Code auf alle Elemente der Datenstruktur anwenden. Das Äquivalent zu Lambda-Funktionen in Haskell sind dabei dann die Blöcke.

Sicher, das ganze funktioniert ähnlich in Java/C# bzw. anderen statischen Sprachen auch - aber nicht ohne zusätzliche Klassen zu erzeugen. Natürlich wird es einfach, sobald man eine Skriptsprache wie Jython oder JavaScript einbindet…

Leave a Reply