Existe-t-il un & # 8220; Faire & # 8230; tandis que & # 8221; boucle en rubis?

StackOverflow https://stackoverflow.com/questions/136793

  •  02-07-2019
  •  | 
  •  

Question

J'utilise ce code pour permettre à l'utilisateur de saisir 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 aurait l'air 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?

Était-ce utile?

La solution

ATTENTION :

Le commence < code > se termine alors que < 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 un échange de courrier électronique dans le 23 nov 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>

Le wiki RosettaCode 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 #.

Autres conseils

  

J'ai trouvé l'extrait suivant lors de la lecture du code source de Tempfile # initialize dans la bibliothèque principale de 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. Observez:

>> begin
?>   puts "do {} while ()" 
>> end while false
do {} while ()
=> nil
     

Comme vous vous en doutez, 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. Ce qui suit est 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 Archive Web et à Forum Ruby Buzz . -Bill the Lézard

Comme ceci:

people = []

begin
  info = gets.chomp
  people += [Person.new(info)] if not info.empty?
end while not info.empty?

Référence: La boucle cachée de Ruby {} While () Loop

Comment ç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 suivant lors de la lecture du code source de Tempfile # initialize dans la bibliothèque principale de 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 tandis que serait évalué avant le contenu de begin ... end , mais ce n'est pas le cas. Observez:

>> begin
?>   puts "do {} while ()" 
>> end while false
do {} while ()
=> nil

Comme vous vous en doutez, 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

Même si je serais heureux de ne plus jamais revoir cet idiot, begin ... end est assez puissant. Ce qui suit est 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

Ceci fonctionne correctement maintenant:

begin
    # statment
end until <condition>

Mais, il sera peut-être supprimé à l'avenir, car l'instruction begin est contre-intuitive. Voir: http://blade.nagaokaut.ac .jp / cgi-bin / scat.rb / ruby ??/ ruby-core / 6745

Matz a recommandé de procéder ainsi:

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>

car sa sémantique est différente de

<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 deuxième construction teste d'abord 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 ligne de construction des 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 & amp; & amp;) de haut en bas. Les humains lisent le code de gauche à droite de haut en bas.

Je suggère plutôt les constructions suivantes:

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 du langage. Mais en tout 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
ppl = []
while (input=gets.chomp)
 if !input.empty?
  ppl << input
 else
 p ppl; puts "Goodbye"; break
 end
end
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top