迭代器的无限产量

发布于 2024-07-14 11:36:07 字数 544 浏览 10 评论 0原文

我正在尝试学习一些红宝石。 想象一下,我正在循环并执行一个长时间运行的过程,在这个过程中,我希望获得一个旋转器,只要需要就可以。

所以我可以这样做:

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 调用需要一个块。 如果我给它一个块,它就会无限期地挂起。

我怎样才能得到这个区块的下一个产量?

I'm trying to learn some ruby.
Imagine I'm looping and doing a long running process, and in this process I want to get a spinner for as long as necessary.

So I could do:

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"

But I thought it'd be cleaner to do:

def spinChar
  a=['|','/','-','\\']
  a.cycle{|x| yield x}
end
# ... skip setup a big loop
print spinChar
# ... do next step of process
print "\b"

Of course the spinChar call wants a block. If I give it a block it'll hang indefinitely.

How can I get just the next yeild of this block?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

清音悠歌 2024-07-21 11:36:08

我喜欢所有这些建议,但我在标准库中找到了生成器,我认为它更符合我想要做的事情:

spinChar=Generator.new{ |g|
  ['|','/','-','\\'].cycle{ |x|
    g.yield x
  }
}
#then
spinChar.next
#will indefinitly output the next character.

在冻结数组上用模数增加的普通数组索引似乎是最快。

弗拉德的帖子很漂亮,但不完全是我想要的。 ),单行增量会更好

spinner 类 中,如果 Ruby 支持 i++(如 GLYPHS[@i++%GLYPHS.length] Max 的 >带有推移的旋转闭包对我来说似乎有点密集,但生成的语法几乎与这个生成器完全相同。 至少我认为这是一个带有 proc 的闭包。

Chuck 的 with_spinner 实际上非常接近我想要的,但是如果您不必像上面那样使用生成器,为什么要中断呢?

Vadim,感谢您指出生成器会很慢。

"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)

I like all these suggestions, but I found the Generator in the standard library, and I think it's more along the lines of what I wanted to do:

spinChar=Generator.new{ |g|
  ['|','/','-','\\'].cycle{ |x|
    g.yield x
  }
}
#then
spinChar.next
#will indefinitly output the next character.

Plain array index increments with modulus on a frozen array seems to be fastest.

Vlad's thread is nifty but not exactly what I wanted. And in spinner class the one-line increment would be nicer if Ruby supported i++ like GLYPHS[@i++%GLYPHS.length]

Max's spinner closure with push shift seems a little intensive to me, but the resulting syntax is almost exactly like this Generator. At least I think that's a closure with proc in there.

Chuck's with_spinner is actually pretty close to what I wanted, but why break if you don't have to with a Generator as above.

Vadim, thanks for pointing out the generator would be slow.

"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)
意中人 2024-07-21 11:36:08

我认为您的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
 => "|" 

I think you were on the right track with cycle. How about something like this:

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
 => "|" 
病毒体 2024-07-21 11:36:08

我认为您不太了解 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

I don't think you quite understand what yield does in Ruby. It doesn't return a value from a block — it passes a value to the block you've passed to the enclosing method.

I think you want something more like this:

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
蝶舞 2024-07-21 11:36:08

曾几何时,我写了一个数组。 但它不仅仅是一个数组,它是一个有指针的数组,所以你可以调用 nextforeverrr!
http://gist.github.com/55955

将此类与简单的迭代器或循环配对,您就可以是金色的。

 a = Collection.new(:a, :b, :c)
 1000.times do |i|
   puts a.current
   a.next
 end

Once upon a time, I wrote an array. But it's not just an array, it's an array that has a pointer, so you can call next foreverrr!
http://gist.github.com/55955

Pair this class with a simple iterator or loop and you are golden.

 a = Collection.new(:a, :b, :c)
 1000.times do |i|
   puts a.current
   a.next
 end
凉城 2024-07-21 11:36:08

如果您能原谅我这么说的话,您的代码有点由内而外。 :)

为什么不:

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

Your code is a bit inside-out, if you'll pardon me saying so. :)

Why not:

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

Now, if you want something like:

with_spinner do
  # do my big task here
end

...then you'd have to use multi-threading:

def with_spinner
  t = Thread.new do
    ['|','/','-','\\'].cycle { |c| print "#{c}\b" ; sleep(1) }
  end
  yield
  Thread.kill(t) # nasty but effective
end
时常饿 2024-07-21 11:36:08

呵呵,我上面的答案都是脏话。

a=['|','/','-','\\']
a << a
a.each {|item| puts item}

hehe, the answer above mine is all dirty.

a=['|','/','-','\\']
a << a
a.each {|item| puts item}
以为你会在 2024-07-21 11:36:07

Ruby 的 yield 无法按照您的方式工作例子会喜欢。 但这可能是一个闭包的好地方:

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< 的想法无论如何, /code>可能会有用。

Ruby's yield does not work in the way your example would like. But this might be a good place for a 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...

In practice I think this solution might be too "clever" for its own good, but understanding the idea of Procs could be useful anyhow.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文