Guida allo studio di Ruby on Rails Blocks, Procs e Lambdas

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.

blocchi

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 precedenzail potere Gli usi dei blocchi in Ruby sono infiniti e li utilizziamo spesso nel nostro codice.


procs

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.


lambda

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.


Conclusione

In questa guida di studio, abbiamo coperto le principali differenze tra Blocks, Proc e Lambdas:

  • I blocchi sono monouso.
  • I Proc esistono come oggetti.
  • Lambdas ha un severo controllo delle argomentazioni.

Per una recensione più approfondita, raccomando le seguenti risorse:

  • Guide di studio dei binari qui su Nettuts+
  • Ruby Proc Documentation
  • Programmazione Ruby 1.9
  • Metaprogramming Ruby: programma come i professionisti di Ruby