J'utilise ce code pour permettre à l'utilisateur d'entrer des noms pendant que le programme les stocke dans un tableau jusqu'à ce qu'ils entrent une chaîne vide (ils doivent appuyer sur entrée après chaque nom):
people = []
info = 'a' # must fill variable with something, otherwise loop won't execute
while not info.empty?
info = gets.chomp
people += [Person.new(info)] if not info.empty?
end
Ce code serait beaucoup plus beau dans une boucle do ... while:
people = []
do
info = gets.chomp
people += [Person.new(info)] if not info.empty?
while not info.empty?
Dans ce code, je n'ai pas à attribuer d'informations à une chaîne aléatoire.
Malheureusement, ce type de boucle ne semble pas exister en Ruby. Quelqu'un peut-il suggérer un meilleur moyen de le faire?
CAUTION:
Le begin <code> end while <condition>
est rejeté par l'auteur de Ruby, Matz. Au lieu de cela, il suggère d'utiliser Kernel#loop
, par exemple.
loop do
# some code here
break if <condition>
end
Voici n échange de courrier électronique en 23 novembre 2005, où Matz déclare:
|> Don't use it please. I'm regretting this feature, and I'd like to
|> remove it in the future if it's possible.
|
|I'm surprised. What do you regret about it?
Because it's hard for users to tell
begin <code> end while <cond>
works differently from
<code> while <cond>
RosettaCode wiki a une histoire similaire:
En novembre 2005, Yukihiro Matsumoto, le créateur de Ruby, a regretté cette fonctionnalité de boucle et a suggéré d'utiliser la boucle Kernel #.
J'ai trouvé l'extrait de code suivant lors de la lecture du code source de
Tempfile#initialize
dans la bibliothèque principale Ruby:begin tmpname = File.join(tmpdir, make_tmpname(basename, n)) lock = tmpname + '.lock' n += 1 end while @@cleanlist.include?(tmpname) or File.exist?(lock) or File.exist?(tmpname)
À première vue, j'ai supposé que le modificateur while serait évalué avant le contenu de begin ... end, mais ce n'est pas le cas. Observer:
>> begin ?> puts "do {} while ()" >> end while false do {} while () => nil
Comme on peut s'y attendre, la boucle continuera à s'exécuter tant que le modificateur est vrai.
>> n = 3 => 3 >> begin ?> puts n >> n -= 1 >> end while n > 0 3 2 1 => nil
Bien que je serais heureux de ne plus jamais revoir cet idiome, commencez ... la fin est assez puissante. Voici un idiome courant pour mémoriser une méthode one-liner sans paramètre:
def expensive @expensive ||= 2 + 2 end
Voici un moyen laid mais rapide de mémoriser quelque chose de plus complexe:
def expensive @expensive ||= begin n = 99 buf = "" begin buf << "#{n} bottles of beer on the wall\n" # ... n -= 1 end while n > 0 buf << "no more bottles of beer" end end
Initialement écrit par Jeremy Voorhis . Le contenu a été copié ici car il semble avoir été retiré du site d'origine. Des copies peuvent également être trouvées dans le Web Archive et à Ruby Buzz Forum . -Bill the Lézard
Comme ça:
people = []
begin
info = gets.chomp
people += [Person.new(info)] if not info.empty?
end while not info.empty?
Référence: Ruby's Hidden do {} while () Loop
Que dis-tu de ça?
people = []
until (info = gets.chomp).empty?
people += [Person.new(info)]
end
Voici l'article en texte intégral du lien mort de hubbardr vers mon blog.
J'ai trouvé l'extrait de code suivant lors de la lecture du code source de Tempfile#initialize
dans la bibliothèque principale Ruby:
begin
tmpname = File.join(tmpdir, make_tmpname(basename, n))
lock = tmpname + '.lock'
n += 1
end while @@cleanlist.include?(tmpname) or
File.exist?(lock) or File.exist?(tmpname)
À première vue, j'ai supposé que le modificateur while
serait évalué avant le contenu de begin...end
, mais ce n'est pas le cas. Observer:
>> begin
?> puts "do {} while ()"
>> end while false
do {} while ()
=> nil
Comme on peut s'y attendre, la boucle continuera à s'exécuter tant que le modificateur est vrai.
>> n = 3
=> 3
>> begin
?> puts n
>> n -= 1
>> end while n > 0
3
2
1
=> nil
Bien que je serais heureux de ne plus jamais revoir cet idiome, begin...end
est assez puissant. Voici un idiome courant pour mémoriser une méthode one-liner sans paramètre:
def expensive
@expensive ||= 2 + 2
end
Voici un moyen laid mais rapide de mémoriser quelque chose de plus complexe:
def expensive
@expensive ||=
begin
n = 99
buf = ""
begin
buf << "#{n} bottles of beer on the wall\n"
# ...
n -= 1
end while n > 0
buf << "no more bottles of beer"
end
end
Cela fonctionne correctement maintenant:
begin
# statment
end until <condition>
Mais, il sera peut-être supprimé ultérieurement, car l'instruction begin
est contre-intuitive. Voir: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/Ruby/ruby-core/6745
Matz (Ruby’s Creator) a recommandé de le faire de la manière suivante:
loop do
# ...
break if <condition>
end
D'après ce que je comprends, Matz n'aime pas la construction
begin
<multiple_lines_of_code>
end while <cond>
parce que sa sémantique est différente de celle
<single_line_of_code> while <cond>
en ce que la première construction exécute le code avant de vérifier la condition, et la seconde teste la condition avant d'exécuter le code (si jamais). Je suppose que Matz préfère conserver la deuxième construction car elle correspond à une construction de ligne d'instructions if.
Je n'ai jamais aimé la deuxième construction, même pour les déclarations if. Dans tous les autres cas, l'ordinateur exécute le code de gauche à droite (par exemple || et &&) de haut en bas. Les humains lisent le code de gauche à droite de haut en bas.
Je suggère les constructions suivantes à la place:
if <cond> then <one_line_code> # matches case-when-then statement
while <cond> then <one_line_code>
<one_line_code> while <cond>
begin <multiple_line_code> end while <cond> # or something similar but left-to-right
Je ne sais pas si ces suggestions seront analysées avec le reste de la langue. Mais dans tous les cas, je préfère garder l’exécution de gauche à droite ainsi que la cohérence linguistique.
a = 1
while true
puts a
a += 1
break if a > 10
end
En voici un autre:
people = []
1.times do
info = gets.chomp
unless info.empty?
people += [Person.new(info)]
redo
end
end