5. Iterators
5.1 Wat is een iterator?
Een interator is een methode die een block of een Proc
object als parameter heeft. In de source word het block direct na de
methode
aanroep geplaatst. Iterators worden gebruikt om gebruikers gestuurde
controle
structuren mogelijk te maken; m.n. loops.
Laten we eens naar een voorbeeld kijken om te zien hoe dit werkt. Iterators worden vaak gebruikt om een bepaalde actie te laten uitvoeren voor ieder element van een verzameling b.v.:
data = [1, 2, 3] |
De each
methode van het array data
kijgt
het
do...end
block doorgegeven en voert dat vervolgens
herhaaldelijk
uit. Bij iedere aanroep worden aan het block alle opeenvolgende
elementen
van het array doorgegeven.
Je kan blocks ook definieeren met {
...}
in plaats
vando
...end
.
data = [1, 2, 3] |
Deze code doet het zelfde als die in het vorige voorbeeld. This code
has
the same meaning as the last example. Erchter in sommige gevallen
zorgen
precedence issues ervoor dat do
...end
en{
...}
zich anders gedragen.
foobar a, b do .. end # foobar is the iterator. |
Dit komt omdat
{...}
sterker gebonden is aan de
voorgaande expressie
dan een do
block. Het eerste voorbeeld is equivalent metfoobar(a,
b) do...
, het tweede met foobar(a, b {...})
.
5.2 Hoe geef ik een block door aan een iterator?
Je zet het block gewoon achter de aanroep van de iterator. Je kan
ook een
Proc
object doorgeven door een de variabele of constante
die
naar het block verwijst vooraf telaten gaan door een &.
5.3 Hoe word een block gebruikt in een iterator?
Er zijn drie manieren om een block in een iterator uit te voeren:
(1)
met het yield
statement, (2) het aan roepen van een Proc
parameter met call
en (3) het geruik van Proc.new
gevolgd door een call
.
Het yield
statement roept het block aan, en geeft
indien nodig
parameters door.
def myIterator |
Als een methode definitie een block als parameter heeft (de laatste
formele
parameter word vooraf gegaan door een ampersand (&)), dan word het
meegegeven
block omgezt in een a Proc
object. Dit kan worden
aangeroeven
met method.call(args...)
.
def myIterator(&b) |
Proc.new
(of de equivalente proc
of lambda
aanroepen) gebruikt in een iterator definition, neemt het gegeven block
en
maakt daar een procedure object van. (proc
and lambda
are effectively synonyms.)
def myIterator |
Misschien verassend maar Proc.new
and friends doen
niets met
het door gegeven block; iedere aanroep vanProc.new
maakt
een
nieuw procedure object van dat zelfde block.
Je kan opvragen of er een block is doorgegeven aan een methode door
het
aanroepen vanblock_given?
.
5.4 What doet Proc.new
zonder block?
Proc.new
zonder block kan geen procedure object
aanmaken en
geeft dus een foutmelding. In een methode definitie, echter impliceerdProc.new
zonder block het bestaan van een block op het moment dat de methode
word
aangeroepen zodat er geen foutmelding word gegeven.
5.5 How kan ik iterators parallel laten runnen?
De oplossing van Matz's in [ruby-talk:5252], gebruikt threads:
require 'thread' |