In questo capitolo faremo una panoramica sui blocchi e sugli iteratori, in modo da avere gli strumenti necessari per affrontare i prossimi capitoli. Anche se sono caratteristiche presenti in altri linguaggi da lungo tempo, è il Ruby che ha reso l'utilizzo di questi potenti strumenti incredibilmente semplice.
Blocchi e iteratori
Iniziamo con un paio di definizioni. Un blocco sintatticamente è una porzione di codice compresa tra le parole chiave do e end oppure tra una coppia di parentesi graffe { e }; convenzionalmente si utilizza la seconda forma per blocchi che occupano una sola riga. Un iteratore invece è un normale metodo che accetta come argomento un blocco, ovvero una funzione anonima che viene eseguita sui parametri passatigli dall'iteratore. È molto più semplice di quello che sembra, vediamo un semplice esempio per chiarire un po' le cose:
> str = "Ciao Mondo"
> str.each_byte {|c| puts c.chr}
C
i
a
o
M
o
n
d
o
Abbiamo utilizzato l'iteratore each_byte della classe String che passa ogni byte della stringa come parametro al blocco tra parentesi graffe. Abbiamo anche passato un parametro (c) tra il metodo e il blocco. La variabile c, locale al blocco, assume quindi di volta in volta il valore passato dal metodo, nel nostro esempio i singoli caratteri delle stringa.
È possibile passare dei parametri anche all'iteratore come a qualsiasi altro metodo. Ad esempio l'iteratore each, o each_line, della classe String accetta come argomento il valore del separatore (n è il valore di default):
> str.each {|c| puts c}
Ciao Mondo
> str.each(' ') {|c| puts c}
Ciao
Mondo
Vedremo la grande utilità degli iteratori quando parleremo degli array e delle altre strutture dati.
Prima di concludere diamo un altro sguardo ai blocchi e vediamo come vanno chiamati dall'interno di un metodo. Subito un esempio che poi commenteremo:
def chiama
puts "Sono nel metodo"
yield
end
chiama { puts "Sono nel blocco" }
eseguendo questo codice otterremo il seguente output:
Sono nel metodo Sono nel blocco
Per richiamare il blocco abbiamo usato l'istruzione yield, che non fa altro richiamare il blocco associato al metodo che lo contiene. È possibile utilizzare più volte yield all'interno di un metodo:
def chiama
yield
puts "Sono nel metodo"
yield
end
e anche passare parametri al blocco tramite yield:
def chiama
puts "Sono nel metodo"
yield(100)
end
chiama { |n| puts "Sono nel blocco e il parametro vale: #{n}" }
In questo modo avremo in output
Sono nel metodo Sono nel blocco e il parametro vale: 100
Apriamo una breve parentesi sul significato di #{espressione} all'interno della stringa passata a puts. In pratica il codice contenuto all'interno delle parentesi viene eseguito e il risultato trasformato in stringa, e nel nostro esempio il tutto è stampato.
Infine possiamo creare un blocco contenente delle normali espressioni:
begin
#espressione1
#espressione2
#...
end
Il valore dell'ultima espressione valutata sarà anche il valore del blocco. Come vedremo tra qualche capitolo begin/end risulta di grande utilità soprattutto nella gestione delle eccezioni.
Se vuoi aggiornamenti su Development inserisci la tua email nel box qui sotto: