488 Stimmen

Gibt es in Ruby eine "do ... while"-Schleife?

Ich verwende diesen Code, um den Benutzer Namen eingeben zu lassen, während das Programm sie in einem Array speichert, bis sie eine leere Zeichenfolge eingeben (sie müssen nach jedem Namen die Eingabetaste drücken):

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

Dieser Code würde in einer do ... while-Schleife viel besser aussehen:

people = []

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

In diesem Code muss ich die Informationen nicht einer zufälligen Zeichenfolge zuordnen.

Leider scheint es diese Art von Schleife in Ruby nicht zu geben. Kann jemand einen besseren Weg vorschlagen, dies zu tun?

706voto

Siwei Punkte 16939

VORSICHT :

Le site begin <code> end while <condition> wird von Rubys Autor Matz abgelehnt. Stattdessen schlägt er die Verwendung von Kernel#loop z.B.

loop do 
  # some code here
  break if <condition>
end 

Hier ist einen E-Mail-Austausch vom 23. November 2005, wo Matz erklärt:

|> 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 hat eine ähnliche Geschichte:

Im November 2005 bedauerte Yukihiro Matsumoto, der Schöpfer von Ruby, diese Schleifenfunktion und schlug vor, Kernel#loop zu verwenden.

190voto

hubbardr Punkte 3095

Beim Lesen des Quelltextes von Tempfile#initialize in der Ruby-Kernbibliothek:

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)

Auf den ersten Blick nahm ich an, dass der while-Modifikator vor dem Inhalt von begin...end ausgewertet werden würde, aber das ist nicht der Fall. Beobachten Sie:

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

Wie zu erwarten, wird die Schleife weiter ausgeführt, solange der Modifikator wahr ist.

>> n = 3
=> 3
>> begin
?>   puts n
>>   n -= 1
>> end while n > 0
3
2
1
=> nil

Obwohl ich froh wäre, diese Redewendung nie wieder zu sehen, ist "begin...end" ziemlich aussagekräftig. Das Folgende ist ein gängiges Idiom, um eine Einzeilermethode ohne Parameter zu memoisieren:

def expensive
  @expensive ||= 2 + 2
end

Hier ist eine hässliche, aber schnelle Methode, um etwas Komplexeres zu memorieren:

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

Ursprünglich geschrieben von Jeremy Voorhis . Der Inhalt wurde hierher kopiert, da er anscheinend von der ursprünglichen Website entfernt wurde. Kopien finden Sie auch in der Web-Archiv und bei Ruby Buzz Forum . -Bill the Lizard

106voto

Blorgbeard Punkte 96796

Zum Beispiel so:

people = []

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

Referenz: Ruby's versteckte do {} while () Schleife

44voto

AndrewR Punkte 10519

Wie wäre es damit?

people = []

until (info = gets.chomp).empty?
  people += [Person.new(info)]
end

14voto

Steely Wing Punkte 14161

Dies funktioniert jetzt korrekt:

begin
    # statment
end until <condition>

Aber es kann in Zukunft entfernt werden, weil die begin Aussage ist kontraintuitiv. Siehe: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/6745

Matz (der Schöpfer von Ruby) empfahl diese Vorgehensweise:

loop do
    # ...
    break if <condition>
end

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X