next up previous contents index
Search Next: Variablen, Blöcke und Iteratoren Up: Kontrollstrukturen und Wertebereiche Previous: Bereiche   Contents   Index

Throw und Catch

Um aus tief verschachtelten Strukturen den Programmfluss über mehrere Ebenen hinweg zu ändern, stellt Ruby das (auch in Lisp vorhandene) Idiom throw und catch zur Verfügung.

kombi = "#{rand(10)}#{rand(10)}"
p geraten = catch(:gefunden) {
  (0..9).each { |a|
    (0..9).each { |b|
      test = "#{a}#{b}#{c}"
      throw(:gefunden, test) if test == kombi
    }
  }
  nil
}

Die im catch-Block aufgeführten Anweisungen werden abgearbeitet, bis die throw-Anweisung in einem Zug aus der innersten Schleife zurück auf die zugehörige catch-Ebene springt.

Dabei kann wie im Beispiel ein Objekt "`geworfen"' werden, das die mit dem gleichen Symbol bereitgestellte catch-Anweisung "`auffängt"'. Fehlt ein korrespondierendes catch, so produziert Ruby einen NameError: uncaught throw '...'.


\epsfig{height=36pt,file=images/chan.eps}Die Schreibweise :dings bezeichnet ein Symbol mit dem Namen "`dings"'. Symbole sind interne Repräsentationen, die für den jeweiligen String eindeutig sind:

:dings.id                   #-> 3619086
"dings".intern.id           #-> 3619086
("d"+"ings").intern.id      #-> 3619086
\epsfig{height=10pt,file=images/ruby.eps}

Bei Bedarf können mehrere catch-Blöcke verschachtelt werden, was aber schnell unübersichtlich wird. Anzumerken ist noch, dass erst während der Ausführung der throw-Anweisung ein passendes catch aktiv sein muss.

def wurf; throw :faenger, "ball"; end
catch(:faenger) { wurf }   #-> "ball"
wurf                       #-> NameError



(C) 2002 by dpunkt.de, Armin Roehrl, Stefan Schmiedl, Clemens Wyss 2002-01-20