質問
ルビーを学ぼうとしています。 ループして長時間実行しているプロセスを想像してください。このプロセスでは、必要なだけスピナーを取得したいです。
だからできる:
a=['|','/','-','\\']
aNow=0
# ... skip setup a big loop
print a[aNow]
aNow += 1
aNow = 0 if aNow == a.length
# ... do next step of process
print "\b"
しかし、私はそれがもっときれいになると思った:
def spinChar
a=['|','/','-','\\']
a.cycle{|x| yield x}
end
# ... skip setup a big loop
print spinChar
# ... do next step of process
print "\b"
もちろん、spinChar呼び出しにはブロックが必要です。ブロックを指定すると、無期限にハングします。
このブロックの次の項目を取得するにはどうすればよいですか
他のヒント
これらの提案はすべて気に入っていますが、ジェネレーターは標準ライブラリにあり、それは私がやりたいことの線に沿っていると思います:
spinChar=Generator.new{ |g|
['|','/','-','\\'].cycle{ |x|
g.yield x
}
}
#then
spinChar.next
#will indefinitly output the next character.
プレーン array index
は、凍結された配列のモジュラスを使用して増分するのが最も速いようです。
Vladのスレッドは気の利いたものですが、まさに私が望んでいたものではありません。また、 spinnerクラス
では、Rubyが GLYPHS [@i ++%GLYPHS.length]
Maxのスピナークロージャ
は、私にとっては少し集中的に思えますが、結果の構文はこのGeneratorとほぼ同じです。少なくとも、そこにprocがあるクロージャだと思います。
Chuckの with_spinner
は実際には私が望んでいたものにかなり近いですが、上記のジェネレーターを使用する必要がないのになぜ壊れるのか。
Vadim、 generator
が遅いと指摘してくれてありがとう。
"Here's a test of 50,000 spins:"
user system total real
"array index" 0.050000 0.000000 0.050000 ( 0.055520)
"spinner class" 0.100000 0.010000 0.110000 ( 0.105594)
"spinner closure" 0.080000 0.030000 0.110000 ( 0.116068)
"with_spinner" 0.070000 0.030000 0.100000 ( 0.095915)
"generator" 6.710000 0.320000 7.030000 ( 7.304569)
cycle
であなたは正しい軌道に乗っていたと思います。このようなものはどうですか:
1.8.7 :001 > spinner = ['|','/','-','\\'].cycle
=> #<Enumerable::Enumerator:0x7f111c165790>
1.8.7 :002 > spinner.next
=> "|"
1.8.7 :003 > spinner.next
=> "/"
1.8.7 :004 > spinner.next
=> "-"
1.8.7 :005 > spinner.next
=> "\\"
1.8.7 :006 > spinner.next
=> "|"
Rubyで yield
が何をするか、あなたはよく理解していないと思います。ブロックから値を返しません&#8212;囲んでいるメソッドに渡したブロックに 値を渡します。
もっとこのようなものが欲しいと思う:
def with_spinner
a=['|','/','-','\\']
a.cycle do |x|
print x
$stdout.flush # needed because standard out is usually buffered
yield # this will call the do-block you pass to with_spinner
end
end
with_spinner do
#process here
#break when done
end
昔々、配列を書きました。しかし、それは単なる配列ではなく、ポインターを持つ配列なので、next foreverrrを呼び出すことができます! http://gist.github.com/55955
このクラスを単純なイテレータまたはループとペアリングすると、黄金になります。
a = Collection.new(:a, :b, :c)
1000.times do |i|
puts a.current
a.next
end
あなたのコードは少し裏返しになっています。 :)
理由:
class Spinner
GLYPHS=['|','/','-','\\']
def budge
print "#{GLYPHS[@idx = ((@idx || 0) + 1) % GLYPHS.length]}\b"
end
end
spinner = Spinner.new
spinner.budge
# do something
spinner.budge
spinner.budge
# do something else
spinner.budge
今、次のようなものが必要な場合:
with_spinner do
# do my big task here
end
...その後、マルチスレッドを使用する必要があります:
def with_spinner
t = Thread.new do
['|','/','-','\\'].cycle { |c| print "#{c}\b" ; sleep(1) }
end
yield
Thread.kill(t) # nasty but effective
end
hehe、私の上の答えはすべて汚いです。
a=['|','/','-','\\']
a << a
a.each {|item| puts item}