私はこのコードを使用して、ユーザーが名前を入力できるようにしながら、プログラムが空の文字列を入力するまでそれらを配列に格納するようにします(各名前の後で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 <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の使用を提案しました。
Rubyコアライブラリの
Tempfile#initialize
のソースを読みながら、私は次のスニペットを見つけました: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
もともと Jeremy Voorhis によって書かれました。元のサイトから削除されたと思われるため、ここにコンテンツをコピーしました。コピーは、 Webアーカイブ および Ruby Buzzフォーラム にもあります。 。 - トカゲを請求する
このような:
people = []
begin
info = gets.chomp
people += [Person.new(info)] if not info.empty?
end while not info.empty?
これはどう?
people = []
until (info = gets.chomp).empty?
people += [Person.new(info)]
end
これがhubbardrの私のブログへのデッドリンクからの全文記事です。
RubyコアライブラリのTempfile#initialize
のソースを読みながら、私は次のスニペットを見つけました:
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
これは現在正しく機能します。
begin
# statment
end until <condition>
しかし、begin
ステートメントは直感に反するので、将来は削除される可能性があります。参照: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/Ruby/ruby-core/6745
Matzはこのようにすることを勧めました:
loop do
# ...
break if <condition>
end
私が集めるものから、Matzはその構成を嫌います
begin
<multiple_lines_of_code>
end while <cond>
なぜなら、それは意味論が違うからです
<single_line_of_code> while <cond>
つまり、最初の構文が条件をチェックする前に最初にコードを実行し、2番目の構文がコードを実行する前に最初に条件をテストします(ある場合)。私は、Matzがifステートメントの1行構成に一致するので、2番目の構成を保持することを好みます。
If文の場合でも、2番目の構文は好きではありません。他のすべての場合では、コンピュータはコードを左から右へ(例えば||や&&)上から下へ実行します。人間はコードを左から右に上から下に読みます。
代わりに次のような構成を提案します。
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
これらの提案が他の言語と一致するかどうかはわかりません。しかし、いずれにせよ私は言語の一貫性と同様に左から右への実行を維持することを好みます。
a = 1
while true
puts a
a += 1
break if a > 10
end
これは別のものです:
people = []
1.times do
info = gets.chomp
unless info.empty?
people += [Person.new(info)]
redo
end
end