Guide d'étude Ruby on Rails Blocks, Procs et Lambdas

Ruby est un langage avec un ensemble de fonctionnalités puissantes - les plus puissantes étant sans aucun doute Blocks, Procs et Lambdas. En bref, ces fonctionnalités vous permettent de transmettre du code à une méthode et de l'exécuter ultérieurement. Malgré l'utilisation régulière de ces fonctionnalités, de nombreux développeurs ne comprennent pas parfaitement les différences subtiles qui les séparent..

Guides d'étude: Lorsque vous postulez pour un emploi en programmation, vous serez souvent confronté à un questionnaire visant à déterminer votre niveau de connaissances et votre expérience dans un sujet donné. Les différents articles de cette série apportent des solutions condensées aux questions que vous pourriez vous attendre à voir lors de tels tests..

Des blocs

Un bloc est un code qui est implicitement transmis à une méthode via l’utilisation de deux accolades., , ou faire… fin syntaxe. C'est une convention commune d'utiliser pour des blocs d'une seule ligne, et faire… fin pour des blocs multilignes. Par exemple, les blocs suivants sont fonctionnellement identiques:

array = [1,2,3,4] array.map! faire | n | n * n end => [1, 4, 9, 16] array = [1,2,3,4] array.map! | n | n * n => [1, 4, 9, 16]

La magie derrière un bloc est la rendement mot-clé; il diffère l'exécution de la méthode d'appel afin d'évaluer le bloc. Le résultat du bloc, le cas échéant, est ensuite évalué par tout code restant dans la méthode. le rendement instruction peut également accepter des paramètres, qui sont ensuite transmis et évalués dans le bloc. Lier cela ensemble, un exemple simple de la carte! La méthode ci-dessus serait la suivante:

class Array def map! self.each_with_index do | valeur, index | self [index] = rendement (valeur) fin fin fin

Cette représentation simple de carte! appelle le chaque_avec_index méthode et remplace l'élément de l'index donné par le résultat du bloc. Bien que ce soit un exemple trivial d’utilisation de bloc, il est utile de montrer rendementle pouvoir. Les utilisations de blocs dans Ruby sont infinies, et nous les utilisons fréquemment dans notre code.


Procs

L'exemple ci-dessus illustre une limitation mineure des blocs: ils sont syntaxiques et jetables. Nous devons ressaisir des blocs chaque fois que nous les réutilisons sur différents tableaux, mais nous pouvons stocker un bloc pour une utilisation ultérieure en utilisant l'objet Ruby Proc. Nous pouvons stocker un Proc dans une variable, puis le transmettre explicitement à toute méthode qui accepte un objet appelable. Réécrire l'exemple ci-dessus en tant que Proc ressemblerait à ceci:

number_squared = Proc.new | n | n * n

Modifions notre carte! méthode pour accepter et appeler l'objet Proc:

class Array def map! (proc_object) self.each_with_index do | valeur, index | self [index] = proc_object.call (valeur) fin fin fin tableau = [1,2,3,4] array.map! (number_squared) => [1, 4, 9, 16]

Prenez note que nous n’utilisons plus le rendement mot-clé; à la place, nous utilisons directement le appel méthode sur l'objet Proc, en lui transmettant la valeur du tableau. Nous recevons le même résultat qu'auparavant, mais nous stockons notre bloc dans une variable pour pouvoir le réutiliser ultérieurement..


Lambdas

La fonction Lambda est presque identique à Procs mais avec deux différences principales. Tout d’abord, un lambda vérifie le nombre d’arguments qu’il reçoit et renvoie un ArgumentError si elles ne correspondent pas. Par exemple:

l = lambda "Je suis un lambda" l.call => "Je suis un lambda" l.call ('arg') ArgumentError: nombre incorrect d'arguments (1 pour 0)

Deuxièmement, lambdas fournit des retours diminutifs - ce qui signifie que lorsqu'un Proc rencontre une instruction return dans son exécution, il arrête la méthode et renvoie la valeur fournie. Lambdas, d’autre part, renvoient leur valeur à la méthode, lui permettant de continuer:

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

Comme vous pouvez le voir proc_math frappe l'instruction de retour à l'intérieur du Proc et renvoie la valeur de 2. En revanche, lambda_math ignore l'instruction de retour et évalue 2 + 2 à la place.

Une dernière remarque: Ruby 1.9 introduit la nouvelle syntaxe lambda "stabby" (représentée avec ->), qui est fonctionnellement identique à la syntaxe lambda traditionnelle, mais la syntaxe "stabby" est beaucoup plus nette..


Conclusion

Dans ce guide d'étude, nous avons couvert les principales différences entre Blocks, Procs et Lambdas:

  • Les blocs sont à usage unique.
  • Les procs existent en tant qu'objets.
  • Les Lambda ont une vérification stricte des arguments.

Pour un examen plus approfondi, je vous recommande les ressources suivantes:

  • Guides d'étude Rails ici sur Nettuts+
  • Documentation Ruby Proc
  • Programmation Ruby 1.9
  • Metaprogramming Ruby: un programme comme les pros de Ruby