我正在努力学习一些红宝石。 想象一下,我正在循环并进行一个长时间运行的过程,在这个过程中,我希望在必要时获得一个微调器。
所以我能做到:
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调用需要一个块。如果我给它一个阻止,它将无限期地挂起。
我怎样才能得到这个街区的下一个?
答案 0 :(得分:6)
Ruby的yield
不能按照你的例子的方式工作。但这可能是closure的好地方:
def spinner()
state = ['|','/','-','\\']
return proc { state.push(state.shift)[0] }
end
spin = spinner
# start working
print spin.call
# more work
print spin.call
# etc...
在实践中,我认为这个解决方案对于自己的好处可能过于“聪明”,但无论如何理解Proc
的想法都会有用。
答案 1 :(得分:5)
我喜欢所有这些建议,但我在标准库中找到了Generator,我认为它更符合我想做的事情:
spinChar=Generator.new{ |g|
['|','/','-','\\'].cycle{ |x|
g.yield x
}
}
#then
spinChar.next
#will indefinitly output the next character.
在冻结数组上使用模数的普通array index
增量似乎是最快的。
弗拉德的线程很漂亮但不完全是我想要的。在spinner class
中,如果Ruby支持i++
GLYPHS[@i++%GLYPHS.length]
带有推移的Max spinner closure
对我来说似乎有点密集,但结果语法几乎就像这个Gene。至少我认为这是一个关闭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)
答案 2 :(得分:5)
我认为你与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
=> "|"
答案 3 :(得分:4)
我不认为你完全理解Ruby中yield
的作用。它不会从块返回值 - 它将值传递给您传递给封闭方法的块。
我想你想要更像这样的东西:
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
答案 4 :(得分:0)
你的代码有点内而外,如果你原谅我这样说的话。 :)
为什么不:
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
答案 5 :(得分:0)
曾几何时,我写了一个数组。但它不只是一个数组,它是一个有指针的数组,所以你可以永远调用下一个! http://gist.github.com/55955
将这个类与一个简单的迭代器或循环配对,你就是金色的。
a = Collection.new(:a, :b, :c)
1000.times do |i|
puts a.current
a.next
end
答案 6 :(得分:0)
a=['|','/','-','\\']
a << a
a.each {|item| puts item}