Frage

Ich versuche, einige Rubine zu lernen. Stellen Sie sich vor mir Looping und einen langen laufenden Prozess zu tun, und in diesem Prozess mag ich so lange wie notwendig, um einen Spinner erhalten.

So konnte ich tun:

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"

Aber ich dachte, es sauberer sein würde zu tun:

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

Natürlich will der spinChar Anruf einen Block. Wenn ich ihm einen Block geben werde es hängt auf unbestimmte Zeit.

Wie kann ich nur die nächste yeild dieses Blocks bekommen?

War es hilfreich?

Lösung

yield funktioniert nicht in der Art und Weise würde Ihr Beispiel mögen. Aber dies könnte ein guter Ort für ein Schließung sein:

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 der Praxis denke ich, diese Lösung könnte auch sein, „klug“ für seine eigenen gut, aber das Verständnis der Idee von Proc s irgendwie nützlich sein könnte.

Andere Tipps

Ich mag all diese Vorschläge, aber ich den Generator in der Standard-Bibliothek gefunden, und ich denke, es ist mehr entlang der Linien von dem, was ich tun wollte:

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

Plain array index Schritte mit einem Modul auf einem gefrorenen Array scheinen am schnellsten zu sein.

Vlads Thread ist geschickt, aber nicht genau das, was ich wollte. Und in spinner class der einzeiligen Zuwachs wäre schöner, wenn Ruby-i++ wie GLYPHS[@i++%GLYPHS.length] unterstützt

Max spinner closure mit Push-Verschiebung scheint ein wenig intensiver zu mir, aber die resultierenden Syntax ist fast genau wie dieser Generator. Zumindest glaube ich, dass ein Verschluss mit proc drin.

Chucks with_spinner ist eigentlich ziemlich nahe, was ich wollte, aber warum brechen, wenn Sie wie oben mit einem Generator nicht haben.

Vadim, Dank für den Hinweis der generator würde langsam sein.

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

Ich glaube, Sie auf dem richtigen Weg mit cycle sind. Wie wäre es so etwas wie folgt aus:

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

Ich glaube nicht, dass Sie ganz verstehen, was yield in Ruby tut. Es gibt keinen Wert aus einem Block zurückkehren -. Es geht Wert der Block, den Sie die umschließende Methode übergeben haben

Ich glaube, Sie etwas mehr wollen wie folgen aus:

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

Es war einmal, schrieb ich ein Array. Aber es ist nicht nur ein Array, es ist ein Array, das einen Zeiger hat, so können Sie neben foreverrr anrufen! http://gist.github.com/55955

Paar dieser Klasse mit einem einfachen Iterator oder Schleife und Sie sind golden.

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

Der Code ist ein bisschen von innen nach außen, wenn Sie mir verzeihen werde so sagen. :)

Warum nicht:

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

Jetzt , wenn Sie so etwas wie:

with_spinner do
  # do my big task here
end

... dann müssen Sie auf 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

hehe, die Antwort über mir ist alles schmutzig.

a=['|','/','-','\\']
a << a
a.each {|item| puts item}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top