Die Programmiersprache Ruby (German Edition)
ein
UnboundMethod
-Objekt eine Methode ohne Bindung an das Objekt dar, für das sie aufgerufen wird. Da eine
UnboundMethod
ungebunden ist, kann sie nicht aufgerufen werden, und die Klasse
UnboundMethod
definiert keine
call
- oder
[]
-Methode.
Um ein
UnboundMethod
-Objekt zu erhalten, verwenden Sie die Methode
instance_method
einer Klasse oder eines Moduls:
unbound_plus = Fixnum.instance_method("+")
In Ruby 1.9 können Sie auch die Methode
public_instance_method
verwenden, um ein
UnboundMethod
-Objekt zu erhalten. Sie funktioniert genau wie
instance_method
, ignoriert jedoch Protected- und Private-Methoden (siehe „7.2 Sichtbarkeit von Methoden: public, protected, private“ ).
Um eine ungebundene Methode aufzurufen, müssen Sie diese zunächst mithilfe der Methode
bind
an ein Objekt binden:
plus_2 = unbound_plus.bind(2) # Die Methode an das Objekt 2 binden
Die Methode
bind
liefert ein
Method
-Objekt zurück, das mit seiner
call
-Methode aufgerufen werden kann:
sum = plus_2.call(2) # => 4
Eine andere Möglichkeit, ein
UnboundMethod
-Objekt zu erhalten, besteht darin, die Methode
unbind
der Klasse
Method
aufzurufen:
plus_3 = plus_2.unbind.bind(3)
In Ruby 1.9 besitzt
UnboundMethod
die Methoden
name
und
owner
, die genauso funktionieren wie bei der Klasse
Method
.
6.8 Funktionale Programmierung
Ruby ist keine funktionale Programmiersprache wie Lisp und Haskell, aber Rubys Blöcke, Procs und Lambdas erleichtern einen funktionalen Programmierstil. Jedes Mal, wenn Sie einen Block mit einem
Enumerable
-Iterator wie
map
or
inject
verwenden, programmieren Sie in einem funktionalen Stil. Hier sehen Sie Beispiele, die die Iteratoren
map
und
inject
verwenden:
# Mittelwert und Standardabweichung eines Array von Zahlen berechnen
mean = a.inject {|x,y| x+y } / a.size
sumOfSquares = a.map{|x| (x-mean)**2 }.inject{|x,y| x+y }
standardDeviation = Math.sqrt(sumOfSquares/(a.size-1))
Wenn der funktionale Programmierstil für Sie attraktiv ist, ist es leicht, Features zu Rubys eingebauten Klassen hinzuzufügen, die die funktionale Programmierung erleichtern. Der Rest dieses Kapitels erörtert einige Möglichkeiten des Arbeitens mit Funktionen. Der Code in diesem Abschnitt ist dicht gepackt und wird als gedankenanregende Untersuchung präsentiert und nicht als Empfehlung für guten Programmierstil. Besonders die Neudefinition von Operatoren führt, wenn sie derart übertrieben stattfindet wie im nächsten Abschnitt, zu Programmen, die für andere schwierig zu lesen und zu pflegen sind!
Was folgt, ist fortgeschrittene Materie, und der Code setzt voraus, dass Sie Kapitel 7 verinnerlicht haben. Deshalb könnten Sie beim ersten Lesen dieses Buchs den Rest dieses Kapitels überspringen.
6.8.1 Eine Funktion auf ein Enumerable anwenden
map
und
inject
sind zwei der wichtigsten durch
Enumerable
definierten Iteratoren. Beide erwarten einen Block. Um Programme auf funktionszentrierte Weise zu schreiben, könnten wir Methoden für unsere Funktionen brauchen, die uns erlauben, diese Funktionen auf das angegebene
Enumerable
-Objekt anzuwenden:
# Dieses Modul definiert Methoden und Operatoren zur funktionalen Programmierung.
module Functional
# Diese Funktion auf jedes Element des angegebenen Enumerable
# anwenden und ein Array von Ergebnissen zurückgeben. Dies ist die
# Umkehrung von Enumerable.map. | wird als Operator-Alias verwendet.
# Lesen Sie "|" als "über" oder "angewendet über".
#
# Beispiel:
# a = [[1,2],[3,4]]
# sum = lambda {|x,y| x+y}
# sums = sum|a # => [3,7]
def apply(enum)
enum.map &self
end
alias | apply
# Verwenden Sie diese Funktion, um ein Enumerable auf eine
# einzelne Größe zu "reduzieren".
# Dies ist das Gegenteil von Enumerable.inject.
# <= wird als Operator-Alias verwendet.
# Merkhilfe: <= sieht aus wie eine Injektionsnadel.
# Beispiel:
# data = [1,2,3,4]
# sum = lambda {|x,y| x+y}
# total = sum<=data # => 10
def reduce(enum)
enum.inject &self
end
alias <= reduce
end
# Diese funktionalen Programmiermethoden zu den Klassen
# Proc und Method hinzufügen.
class Proc; include Functional; end
class Method; include Functional; end
Beachten Sie, dass wir Methoden in einem Modul namens
Functional
definieren, und dann dieses Modul sowohl in die Klasse
Proc
als auch in
Method
einfügen. Auf diese Weise funktionieren
apply
und
reduce
sowohl für
Proc
- als auch für
Method
-Objekte. Die meisten der nachfolgenden Methoden definieren ebenfalls Methoden in diesem
Functional
-Modul, so dass sie sowohl
Weitere Kostenlose Bücher