Ich lambda, Du Proc? 0

Posted by fwoeck
on Wednesday, January 07

alles was Sie schon immer über Closures wissen wollten…

... findet sich an dieser Stelle:

www.robertsosinski.com

Zusamenfassung

  • Ein block ist im wesentlichen ein einmal-Proc
  • Procs sind eigenständige Objekte, die Variablen zugewiesen werden können
  • Wann setze ich blocks, wann Procs ein?
    • block: eine Methode soll in mehrere kleinere Stücke zerlegt werden, mit denen die User interagieren
    • block: mehrere Ausdrücke sollen – wie bei einer DB-Migration – atomar abgearbeitet werden
    • Proc: Codeblöcke sollen wiederverwendet werden
    • Proc: eine Methode soll mehr als ein Callback haben (d.h. es werden z.B. zwei Procs in einem Hash an eine Methode übergeben)
  • Im Gegensatz zu Procs prüfen lambdas die Anzahl der übergebenen Argumente
  • Das return-Statement eines Proc beendet die umgebende Methode und retourniert einen Wert
  • Das return-Statement eines lambdas beendet die umgebende Methode nicht, sondern lässt diese weiterlaufen
  • Procs sind einfache Codeschnipsel, während lambdas ganze Methoden sind. Daher überschreiben lambda-returns auch nicht das return der sie umgebenden Methode
  • Man kann sagen: lambdas sind anonyme Methoden
  • Argumente dürfen kein return-Statement enthalten
  • Wird dies aber nötig, so hilft statt der Verwendung eines Proc als Argument die eines lambdas, weil das return dann durch eine (lambda-)Methode gekapselt ist
  • die Methode method konvertiert reguläre Methoden (def fn … end) in lambdas – damit werden sie als Argumente an andere Methoden übergebbar
  • unstimmig?: lambdas gehören formal der Klasse Proc an. Der Autor vermutet, dass sich dies vielleicht künftig ändern könnte.

Anlage

Und falls der Link mal totläuft, gibt’s hier noch eine pdf-Kopie:

understanding_closures.pdf

ruby-Basics: yield 0

Posted by fwoeck
on Thursday, December 04
1
2
3
def filter arr
  arr.select {|f| yield f}
end

Was macht das?

yield erwartet einen Block. Der Aufruf muss also generell lauten:

x = filter(<array>) {|x| fn(x)}

Damit lassen sich verschiedene Filter bauen:

>> filter([1,2,3,4,5,6]) {|y| y % 2 == 0}
=> [2, 4, 6]
>> filter(["abc","def","ghi"]) {|y| y =~ /e/}
=> ["def"]

Bemerkenswert: die Klammern dürfen nicht entfallen:

>> filter ["abc","def","ghi"] {|y| y =~ /e/}
SyntaxError: compile error

Was, wenn ich das “y =~…” in eine eigene Funktion kleiden wollte?

1
2
3
def iseish? x
  x =~ /e/
end
>> iseish?("hu")
=> nil
>> iseish?("heu")
=> 1

>> filter(["abc","def","ghi"], &method(:iseish?))
=> ["def"]