179 votes

do..end vs accolades pour les blocs en Ruby

J'ai un collègue qui essaie activement de me convaincre que je ne devrais pas utiliser do..end mais plutôt les accolades pour définir des blocs multilignes en Ruby.

Je suis fermement convaincu qu'il ne faut utiliser les accolades que pour les phrases courtes d'une ligne et les do..end pour tout le reste. Mais j'ai pensé que je pouvais m'adresser à la communauté pour trouver une solution.

Alors, lequel des deux est le meilleur, et pourquoi ? (Exemple d'un code "shoulda")

context do
  setup { do_some_setup() }
  should "do somthing" do
    # some more code...
  end
end

ou

context {
  setup { do_some_setup() }
  should("do somthing") {
    # some more code...
  }
}

Personnellement, le simple fait de regarder ce qui précède répond à la question pour moi, mais je voulais ouvrir cette question à l'ensemble de la communauté.

4 votes

Je me demande juste quels sont les arguments de vos collègues pour l'utilisation d'un appareil dentaire ? Ça ressemble plus à une préférence personnelle qu'à une question de logique.

7 votes

Si vous voulez une discussion, faites-en un wiki communautaire. A votre question : C'est juste un style personnel. Je préfère les accolades bouclées car elles ont l'air plus ringardes.

10 votes

Ce n'est pas une question de préférence, il y a des raisons syntaxiques d'utiliser l'une plutôt que l'autre, en plus des raisons stylistiques. Plusieurs des réponses expliquent pourquoi. Ne pas utiliser la bonne méthode peut provoquer des bogues très subtils qui sont difficiles à trouver si un autre choix "stylistique" est fait de ne jamais utiliser de parenthèses enveloppantes pour les méthodes.

275voto

Pan Thomakos Points 19946

La convention générale consiste à utiliser do..end pour les blocs de plusieurs lignes et les accolades pour les blocs d'une seule ligne, mais il existe également une différence entre les deux qui peut être illustrée par cet exemple :

puts [1,2,3].map{ |k| k+1 }
2
3
4
=> nil
puts [1,2,3].map do |k| k+1; end
#<Enumerator:0x0000010a06d140>
=> nil

Cela signifie que {} a une plus grande priorité que do..end, donc gardez cela à l'esprit lorsque vous décidez ce que vous voulez utiliser.

P.S. : Un autre exemple à garder à l'esprit pendant que vous développez vos préférences.

Le code suivant :

task :rake => pre_rake_task do
  something
end

signifie vraiment :

task(:rake => pre_rake_task){ something }

Et ce code :

task :rake => pre_rake_task {
  something
}

signifie vraiment :

task :rake => (pre_rake_task { something })

Donc pour obtenir la définition réelle que vous voulez, avec des accolades, vous devez faire :

task(:rake => pre_rake_task) {
  something
}

Peut-être que l'utilisation d'accolades pour les paramètres est quelque chose que vous voulez faire de toute façon, mais si vous ne le faites pas, il est probablement préférable d'utiliser do..end dans ces cas pour éviter cette confusion.

49 votes

Je vote pour que l'on utilise toujours des parenthèses autour des paramètres des méthodes afin de contourner le problème.

0 votes

@the Tin Man : Vous utilisez même les parenthèses dans Rake ?

10 votes

C'est une habitude de programmation de la vieille école pour moi. Si un langage supporte les parenthèses, je les utilise.

61voto

David Brown Points 7090

De Programmation de Ruby :

Les accolades ont une préséance élevée ; do a une préséance faible. Si l'invocation de la méthode comporte des paramètres qui ne sont pas entre parenthèses, la forme accolade d'un bloc se lie au dernier paramètre, et non à l'invocation globale. La forme do se lie à l'invocation.

Donc le code

f param {do_something()}

Lier le bloc à la param alors que le code

f param do do_something() end

Lier le bloc à la fonction f .

Toutefois, ce n'est pas un problème si vous mettez les arguments de la fonction entre parenthèses.

9 votes

+1 "Cependant, ce n'est pas un problème si vous mettez les arguments de la fonction entre parenthèses". Je le fais par habitude, plutôt que de me fier au hasard et aux caprices de l'interprète :-)

4 votes

@theTinMan, si votre interprète utilise le hasard dans son analyseur syntaxique, il vous faut un nouvel interprète.

2 votes

@PaulDraper - en effet, mais toutes les langues ne sont pas d'accord sur ce point. Mais (je pense) qu'il est plutôt rare que les parenthèses ne "fassent pas leur travail", donc l'utilisation universelle des parenthèses vous évite d'avoir à vous souvenir des décisions "aléatoires" prises par les concepteurs du langage - même si elles sont fidèlement exécutées par les implémenteurs des compilateurs et des interpréteurs.

16voto

GSto Points 13106

Il y a plusieurs points de vue sur ce sujet, c'est vraiment une question de préférence personnelle. De nombreux rubyistes adoptent l'approche que vous suivez. Cependant, deux autres styles courants consistent à toujours utiliser l'un ou l'autre, ou à utiliser {} pour les blocs qui renvoient des valeurs, et do ... end pour les blocs qui sont exécutés pour des effets secondaires.

3 votes

Il ne s'agit pas seulement d'une question de préférence personnelle. La liaison des paramètres peut provoquer de subtils bogues si les paramètres de la méthode ne sont pas mis entre parenthèses.

1 votes

Je ne fais pas actuellement la dernière option, mais je suis +1-ing pour avoir mentionné que certaines personnes adoptent cette approche.

0 votes

Avdi Grimm plaide en ce sens dans un billet de blog : devblog.avdi.org/2011/07/26/

9voto

Beerlington Points 25012

La règle la plus courante que j'ai vue (plus récemment dans Eloquent Ruby ) est :

  • S'il s'agit d'un bloc de plusieurs lignes, utilisez do/end.
  • S'il s'agit d'un bloc d'une seule ligne, utilisez {}.

8voto

DigitalRoss Points 80400

Je vote pour do / end


La convention est do .. end pour les lignes multiples et { ... } pour les bonnes blagues.

Mais j'aime do .. end mieux, donc quand j'ai une doublure, j'utilise do .. end de toute façon mais le formater comme d'habitude pour faire/finir en trois lignes. Cela rend tout le monde heureux.

  10.times do 
    puts ...
  end

Un problème avec { } c'est qu'il est hostile au mode poétique (parce qu'il est étroitement lié au dernier paramètre et non à l'appel de la méthode dans son ensemble, et qu'il faut donc inclure les parenthèses de la méthode) et qu'il n'est pas aussi joli, à mon avis. Ils ne sont pas des groupes d'énoncés et ils s'opposent aux constantes de hachage pour la lisibilité.

De plus, j'ai vu assez de { } dans les programmes C. La méthode de Ruby, comme toujours, est meilleure. Il y a exactement un type de if et vous ne devez jamais revenir en arrière pour convertir une déclaration en une déclaration composée.

2 votes

"J'ai vu assez de { } dans les programmes C"... et Perl. Et, +1 pour plusieurs déclarations là-dedans et pour la défense des styles de codage zen de Ruby :-)

1 votes

Strictement parlant, il existe une autre syntaxe "if" - le postfixe "if" ( do_stuff if x==1 ), qui est un peu ennuyeux à convertir en syntaxe régulière. Mais c'est une autre discussion.

0 votes

Il y a des préfixes if , postfix if , postfix unless (également une sorte de if un si-non) et une ligne if avec then . La méthode Ruby consiste à disposer de nombreuses façons d'exprimer en fait quelque chose qui est toujours la même chose, bien pire que ce que propose le C qui suit des règles très simples et strictes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X