Ruby è un linguaggio con un insieme di potenti funzionalità: il più potente è probabilmente Blocks, Procs e Lambdas. In breve, queste funzionalità consentono di passare il codice a un metodo ed eseguirlo in un secondo momento. Nonostante utilizzino regolarmente queste funzionalità, molti sviluppatori non comprendono appieno le sottili differenze tra di loro.
Guide di studio: Quando fai domanda per un lavoro di programmazione, ti verrà spesso presentato un quiz che intende determinare il tuo livello di conoscenza ed esperienza in un determinato argomento. I vari articoli di questa serie forniscono soluzioni condensate alle domande che potresti aspettarti di vedere in questi test.Un blocco è un codice che è passato implicitamente a un metodo attraverso l'uso di entrambe le parentesi graffe, ...
, o fai ... fine
sintassi. È convenzione comune da usare ...
per blocchi a linea singola, e fai ... fine
per blocchi a più linee. Ad esempio, i seguenti blocchi sono funzionalmente uguali:
array = [1,2,3,4] array.map! do | n | n * n end => [1, 4, 9, 16] array = [1,2,3,4] array.map! | n | n * n => [1, 4, 9, 16]
La magia dietro un blocco è il dare la precedenza
parola chiave; rimanda l'esecuzione del metodo di chiamata per valutare il blocco. Il risultato del blocco, se presente, viene quindi valutato da qualsiasi codice rimanente nel metodo. Il dare la precedenza
l'istruzione può anche accettare parametri, che vengono quindi passati e valutati all'interno del blocco. Legando questo insieme, un semplice esempio di carta geografica!
sopra il metodo sarebbe il seguente:
class array mappa di def. self.each_with_index do | valore, indice | self [indice] = rendimento (valore) fine fine fine
Questa semplice rappresentazione di carta geografica!
chiama il each_with_index
metodo e sostituisce l'elemento all'indice indicato con il risultato del blocco. Mentre questo è un esempio banale di utilizzo del blocco, aiuta a mostrare dare la precedenza
il potere Gli usi dei blocchi in Ruby sono infiniti e li utilizziamo spesso nel nostro codice.
L'esempio sopra mostra una limitazione minore dei blocchi: sono sintassi e usa e getta. Dobbiamo ridigitare i blocchi ogni volta che li riutilizziamo su array diversi, ma possiamo memorizzare un blocco per un utilizzo futuro utilizzando l'oggetto Proc Ruby. Possiamo memorizzare un Proc in una variabile e quindi passarlo esplicitamente a qualsiasi metodo che accetti un oggetto callable. Riscrivere l'esempio precedente come Proc sembrerebbe il seguente:
number_squared = Proc.new | n | n * n
Modifichiamo il nostro carta geografica!
metodo per accettare e chiamare l'oggetto Proc:
class Array def map! (proc_object) self.each_with_index do | value, index | self [indice] = proc_object.call (valore) array end end end = [1,2,3,4] array.map! (number_squared) => [1, 4, 9, 16]
Prendi nota che non usiamo più il dare la precedenza
parola chiave; invece, usiamo direttamente il chiamata
metodo sull'oggetto Proc, passandogli il valore dall'array. Riceviamo lo stesso risultato di prima, ma archiviamo il nostro blocco in una variabile per riutilizzarla in un secondo momento.
Le funzioni Lambda sono quasi identiche a Procs ma con due differenze chiave. Primo, un lambda controlla il numero di argomenti che riceve e restituisce un ArgumentError
se non corrispondono. Per esempio:
l = lambda "I'm a lambda" l.call => "Sono un lambda" l.call ('arg') ArgumentError: numero errato di argomenti (1 per 0)
In secondo luogo, lambdas fornisce rendimenti diminutivi - ciò significa che quando un Proc incontra un'istruzione return nella sua esecuzione, interrompe il metodo e restituisce il valore fornito. Lambdas, d'altra parte, restituisce il loro valore al metodo, permettendogli di continuare:
def proc_math Proc.new return 1 + 1 .call return 2 + 2 end def lambda_math lambda return 1 + 1 .call return 2 + 2 end proc_math # => 2 lambda_math # => 4
Come potete vedere proc_math
colpisce l'istruzione return all'interno di Proc e restituisce il valore di 2
. In contrasto, lambda_math
salta la dichiarazione di ritorno e valuta invece 2 + 2.
Un'ultima nota: Ruby 1.9 introduce la nuova sintassi lambda "stabby" (rappresentata con ->), che è funzionalmente identica alla tradizionale sintassi lambda, ma la sintassi "stabby" è molto più pulita.
In questa guida di studio, abbiamo coperto le principali differenze tra Blocks, Proc e Lambdas:
Per una recensione più approfondita, raccomando le seguenti risorse: