474

私はこのコードを使用して、ユーザーが名前を入力できるようにし、プログラムが空の文字列を入力するまで名前を配列に格納します(各名前の後に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には存在しないようです。誰かがこれを行うためのより良い方法を提案できますか?

4

10 に答える 10

681

注意:

begin <code> end while <condition>、Ruby の作者 Matz によって拒否されました。代わりに、彼は を使用することを提案していKernel#loopます。

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

以下は、2005 年 11 月 23 日のメール交換で、Matz は次のように述べています。

|> 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 の作成者である松本幸宏は、このループ機能を後悔し、Kernel#loop の使用を提案しました。

于 2012-05-23T05:28:38.377 に答える
188

Tempfile#initializeRuby コア ライブラリでのソースを読んでいるときに、次のスニペットを見つけました。

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)

一見、begin...end の内容よりも前に while 修飾子が評価されると思っていましたが、そうではありません。観察:

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

ご想像のとおり、修飾子が true の間、ループは実行され続けます。

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

このイディオムを二度と見なくてよかったのですが、begin...end は非常に強力です。以下は、パラメーターのないワンライナー メソッドをメモ化するための一般的なイディオムです。

def expensive
  @expensive ||= 2 + 2
end

これは、もっと複雑なものをメモするための醜い、しかし手っ取り早い方法です:

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 アーカイブおよびRuby Buzz Forumにもあります。-トカゲのビル

于 2008-09-25T23:19:05.457 に答える
103

このような:

people = []

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

参考:Rubyの隠しdo {} while()ループ

于 2008-09-25T23:20:30.147 に答える
44

これはどう?

people = []

until (info = gets.chomp).empty?
  people += [Person.new(info)]
end
于 2008-09-25T23:24:03.133 に答える
12

これがhubbardrの私のブログへのデッドリンクからの全文記事です。

Tempfile#initializeRubyコアライブラリのソースを読んでいるときに、次のスニペットを見つけました。

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)

一見、while修飾子はの内容の前に評価されると思いましbegin...endたが、そうではありません。観察:

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

ご想像のとおり、修飾子がtrueの間、ループは実行を継続します。

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

このイディオムが二度と見られないことを嬉しく思いますが、begin...end非常に強力です。以下は、パラメータのないワンライナーメソッドをメモ化するための一般的なイディオムです。

def expensive
  @expensive ||= 2 + 2
end

これは醜いですが、もっと複雑なものをメモ化する簡単な方法です。

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
于 2010-07-22T15:27:46.767 に答える
11

これは正しく機能するようになりました。

begin
    # statment
end until <condition>

beginただし、このステートメントは直感に反するため、将来削除される可能性があります。参照: http: //blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/6745

Matz(Ruby's Creator)は、次のようにすることを推奨しました。

loop do
    # ...
    break if <condition>
end
于 2013-02-17T06:26:31.810 に答える
3
a = 1
while true
  puts a
  a += 1
  break if a > 10
end
于 2010-08-04T23:51:43.687 に答える
2

ここに別のものがあります:

people = []
1.times do
  info = gets.chomp
  unless info.empty? 
    people += [Person.new(info)]
    redo
  end
end
于 2011-11-10T12:38:58.283 に答える
-3
ppl = []
while (input=gets.chomp)
 if !input.empty?
  ppl << input
 else
 p ppl; puts "Goodbye"; break
 end
end
于 2010-01-11T18:47:58.170 に答える