Bei der Programmierung eines Suchalgorithmus in Rails habe ich bei der Methode Enumerable#find einen einfachen Weg gesucht, die optionale Callback-Methode _ifnone_ zu setzen.
Die Intention des Algorithmus ist, falls es kein passendes Element (item) zur gestellten Suchbedingung gibt (item search condition), ein bestimmtes (hier: das letzte) Element zurückzugeben, statt nil.
Dafür bin ich unter Funktionale Programmierung auf den folgenden für mich sehr hilfreichen Code-Snippet gestoßen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # Dieser Ausdruck verhindert eine doppelte Definition der Operatoren [] und []= unless :test.respond_to?(:[]) # # Operatoren [] und []= zur Klasse Symbol hinzufügen, um Singleton-Methoden # von Objekten zu lesen und zu setzen. Lies : als "Methode" und [] als "von". # Also bedeutet zum Beispiel :m[o] "Methode m von o". # class Symbol # Die durch dieses Symbol benannte Methode von obj zurückgeben. Dies kann # eine Singleton-Mehtode von obj (etwa eine Klassenmethode) oder eine Instanz- # methode sein, die in obj.class definiert oder von einer Oberklasse übernommen # wurde. # Beispiele: # creator = :new[Object] #Klassenmethode Object.new # doubler = :*[2] # *-Methode der Fixnum 2 # def [](obj) obj.method self end # Eine Singleton-Methode für Objekt o definieren und Proc oder Method f # als Rumpf verwenden. Dieses Symbol dient als Name der Methode. # Beispiele: # :singleton[o] = lamba { puts "Dies ist eine Singleton-Methode von o" } # :class_method[String] = lamba { puts "Dies ist eine Klassenmethode" } # # Beachten: Sie können so keine Instanzmethoden erzeugen. Siehe Module.[]= # def []=(o,f) # self einer Variablen zuweisen, da der folgende Block einen anderen Kontext # haben wird. sym = self # Dies ist das Objekt, für das wir Singleton-Methoden definieren. eigenclass = (class << o; self end) # define_method ist privat, so dass wir instance_eval verwenden müssen. eigenclass.instance_eval { define_method(sym, f) } end end end |
Mein Anwendungsfall sieht dann folgendermaßen aus:
34 35 36 | ... valuearray.find(:last[valuearray]) {|item| /* item search condition */ } ... |
Als Fallback für eine nicht erfolgreiche Suche verwende ich :last[valuearray], die last-Methode von dem Array-Objekt valuearray.
Auch wenn dieses Beispiel für den durchschnittlichen Ruby-Entwickler etwas überzogen daherkommt,
soll es die Aufmerksamkeit für diesen Themenkomplex der Programmiersprache anregen und die
Vielseitigkeit und Flexibilität von Ruby zeigen.