En utilisant do bloc vs crochets {}

Nouveau sur Ruby, mettez vos gants de débutant.

Y a-t-il une différence (obscure ou pratique) entre les deux extraits suivants?

my_array = [:uno, :dos, :tres] my_array.each { |item| puts item } my_array = [:uno, :dos, :tres] my_array.each do |item| puts item end 

Je me rends compte que la syntaxe des parenthèses vous permettrait de placer le bloc sur une seule ligne

 my_array.each { |item| puts item } 

mais en dehors de cela, y a-t-il des raisons impérieuses d’utiliser une syntaxe plutôt qu’une autre?

Ruby cookbook indique que la syntaxe des parenthèses a un ordre de priorité plus élevé que do..end

Gardez à l’esprit que la syntaxe entre crochets a une priorité plus élevée que la syntaxe do..end. Considérez les deux extraits de code suivants:

 1.upto 3 do |x| puts x end 1.upto 3 { |x| puts x } # SyntaxError: comstack error 

Le deuxième exemple ne fonctionne que lorsque les parenthèses sont utilisées, 1.upto(3) { |x| puts x } 1.upto(3) { |x| puts x }

C’est une question un peu ancienne mais je voudrais essayer d’expliquer un peu plus sur {} et do .. end

comme il est dit avant

la syntaxe de parenthèse a un ordre de priorité plus élevé que do..end

mais comment celui-ci fait la différence:

 method1 method2 do puts "hi" end 

dans ce cas, method1 sera appelé avec le bloc do..end et method2 sera passé à method1 en argument! ce qui équivaut à method1(method2){ puts "hi" }

mais si tu dis

 method1 method2{ puts "hi" } 

alors méthode2 sera appelée avec le bloc, la valeur retournée sera transmise à method1 en tant qu’argument. Ce qui équivaut à method1(method2 do puts "hi" end)

 def method1(var) puts "inside method1" puts "method1 arg = #{var}" if block_given? puts "Block passed to method1" yield "method1 block is running" else puts "No block passed to method1" end end def method2 puts"inside method2" if block_given? puts "Block passed to method2" return yield("method2 block is running") else puts "no block passed to method2" return "method2 returned without block" end end #### test #### method1 method2 do |x| puts x end method1 method2{ |x| puts x } 

#### sortie ####

 #inside method2 #no block passed to method2 #inside method1 #method1 arg = method2 returned without block #Block passed to method1 #method1 block is running #inside method2 #Block passed to method2 #method2 block is running #inside method1 #method1 arg = #No block passed to method1 

En règle générale, la convention consiste à utiliser {} lorsque vous effectuez une petite opération, par exemple un appel de méthode ou une comparaison, etc.

 some_collection.each { |element| puts element } 

Mais si vous avez une logique un peu complexe qui va à plusieurs lignes, alors utilisez do .. end like:

 1.upto(10) do |x| add_some_num = x + rand(10) puts '*' * add_some_num end 

Fondamentalement, cela revient à, si votre logique de bloc passe à plusieurs lignes et ne peut pas être installée sur la même ligne, alors utilisez do .. end et si votre logique de bloc est simple et une simple ligne de code, utilisez alors {} .

Il y a deux styles communs pour choisir do end vs. { } pour les blocs dans Ruby:

Le premier et très commun style a été popularisé par Ruby on Rails, et repose sur une règle simple de single vs. multi-line:

  • Utilisez des accolades { } pour les blocs à une seule ligne
  • Utilisez do end pour les blocs multi-lignes

Cela a du sens parce que do / end se lit mal dans un one-liner, mais pour les blocs multi-lignes, laisser une fermeture } sur sa propre ligne est incompatible avec tout ce qui utilise end in ruby, comme les définitions de module, classe et méthode ( def etc.) et structures de contrôle ( if , while , case , etc.)

Le second style, moins fréquemment vu, est connu sous le nom de sémantique, ou ” Weirich Braces “, proposé par le regretté Jim Weirich:

  • Utilisez do end pour les blocs procéduraux
  • Utilisez des accolades { } pour les blocs fonctionnels

Cela signifie que lorsque le bloc est évalué pour sa valeur de retour , il doit être chaîné et les accolades {} sont plus appropriées pour le chaînage des méthodes.

D’un autre côté, lorsque le bloc est évalué pour ses effets secondaires , alors la valeur de retour est sans conséquence, et le bloc ne fait que “faire” quelque chose, ce qui n’a aucun sens d’être enchaîné.

Cette distinction dans la syntaxe donne une signification visuelle à l’évaluation du bloc et indique si vous devez ou non vous soucier de sa valeur de retour.

Par exemple, ici, la valeur de retour du bloc est appliquée à chaque élément:

 items.map { |i| i.upcase } 

Cependant, ici, il n’utilise pas la valeur de retour du bloc. Cela fonctionne de manière procédurale et fait un effet secondaire avec:

 items.each do |item| puts item end 

Un autre avantage du style sémantique est que vous n’avez pas besoin de modifier les accolades pour faire / terminer simplement parce qu’une ligne a été ajoutée au bloc.

À titre d’observation, les blocs fonctionnels coïncidant sont souvent une ligne et les blocs procéduraux (par exemple, la configuration) sont multi-lignes. Donc, suivre le style Weirich finit par ressembler presque au style Rails.