我使用这段代码让用户输入名称,而程序将它们存储在一个数组中,直到他们输入一个空字符串(他们必须在每个名称后按enter):

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

这段代码在do…while循环:

people = []

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

在这段代码中,我不需要将信息分配给一些随机字符串。

不幸的是,Ruby中似乎不存在这种类型的循环。谁能提出一个更好的方法来做这件事?


当前回答

据我所知,马茨不喜欢这种说法

begin
    <multiple_lines_of_code>
end while <cond>

因为它的语义是不同的

<single_line_of_code> while <cond>

第一个构造在检查条件之前先执行代码, 第二个构造在执行代码(如果有的话)之前先测试条件。我认为Matz更喜欢保留第二个结构,因为它匹配if语句的一行结构。

我从来不喜欢第二个结构,即使是if语句。在所有其他情况下,计算机 从左到右执行代码(例如;||和&&)从上到下。人类从左到右阅读代码 全面。

我建议使用以下结构:

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

我不知道这些建议是否能与语言的其余部分一起解析。但是无论如何 我更喜欢保持从左到右的执行以及语言的一致性。

其他回答

I found the following snippet while reading the source for Tempfile#initialize in the Ruby core library: 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) At first glance, I assumed the while modifier would be evaluated before the contents of begin...end, but that is not the case. Observe: >> begin ?> puts "do {} while ()" >> end while false do {} while () => nil As you would expect, the loop will continue to execute while the modifier is true. >> n = 3 => 3 >> begin ?> puts n >> n -= 1 >> end while n > 0 3 2 1 => nil While I would be happy to never see this idiom again, begin...end is quite powerful. The following is a common idiom to memoize a one-liner method with no params: def expensive @expensive ||= 2 + 2 end Here is an ugly, but quick way to memoize something more complex: 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

原作者:Jeremy Voorhis这里的内容是复制的,因为它似乎是从原始站点删除的。副本也可以在Web Archive和Ruby Buzz论坛上找到。——蜥蜴比尔

是这样的:

people = []

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

参考:Ruby的Hidden do {} while()循环

ppl = []
while (input=gets.chomp)
 if !input.empty?
  ppl << input
 else
 p ppl; puts "Goodbye"; break
 end
end

现在可以正常工作了:

begin
    # statment
end until <condition>

但是,它可能在将来被删除,因为begin语句是违反直觉的。参见:http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/6745

Matz (Ruby的创造者)建议这样做:

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

警告:

开始<代码>结束时<条件>被Ruby的作者Matz拒绝。相反,他建议使用Kernel#循环,例如:

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

以下是Matz在2005年11月23日的一封电子邮件交流:

|> 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上也有类似的故事:

在2005年11月期间,Ruby的创建者松本幸弘(Yukihiro Matsumoto)后悔了这个循环特性,并建议使用Kernel#loop。