Question

J'essaie d'apprendre du rubis. Imaginez que je tourne en boucle et que je travaille sur un long processus, et que je souhaite obtenir un spinner aussi longtemps que nécessaire.

Je pourrais donc faire:

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"

Mais je pensais que ce serait plus propre de faire:

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

Bien sûr, l'appel de spinChar veut un bloc. Si je le bloque, il sera suspendu indéfiniment.

Comment puis-je obtenir la prochaine année de ce bloc?

Était-ce utile?

La solution

Le rendement de Ruby ne fonctionne pas. la façon dont votre exemple aimerait. Mais cela pourrait être un bon endroit pour une clôture :

def spinner()
  state = ['|','/','-','\\']
  return proc { state.push(state.shift)[0] }
end

spin = spinner

# start working
print spin.call
# more work
print spin.call
# etc...

En pratique, je pense que cette solution est peut-être trop "intelligente". pour son propre bien, mais en comprenant l'idée de Proc s pourrait être utile de toute façon.

Autres conseils

J'aime toutes ces suggestions, mais j'ai trouvé le générateur dans la bibliothèque standard, et je pense qu'il va plus dans le sens de ce que je voulais faire:

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

Un index de tableau simple semble être le plus rapide avec un module sur un tableau gelé.

Le fil de Vlad est chouette mais pas exactement ce que je voulais. Et dans spinner class , l'incrément d'une ligne serait plus agréable si Ruby supportait i ++ comme GLYPHS [@i ++% GLYPHS.length]

La fermeture de spinner de Max avec push-shift me semble un peu intensive, mais la syntaxe obtenue est presque identique à celle de ce générateur. Au moins, je pense qu’il s’agit d’une fermeture avec proc.

Le with_spinner de Chuck est en fait assez proche de ce que je voulais, mais pourquoi rompre si vous n'avez pas à utiliser un générateur comme ci-dessus.

Vadim, merci d'avoir signalé que le générateur serait lent.

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

Je pense que vous êtes sur la bonne voie avec cycle . Que diriez-vous de quelque chose comme ça:

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

Je ne pense pas que vous compreniez bien ce que cède fait dans Ruby. Il ne renvoie pas de valeur d'un bloc & # 8212; il transmet une valeur à le bloc que vous avez passé à la méthode englobante.

Je pense que vous voulez quelque chose de plus semblable à ceci:

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

Il était une fois, j’ai écrit un tableau. Mais ce n'est pas simplement un tableau, c'est un tableau qui a un pointeur, vous pouvez donc appeler ensuite foreverrr! http://gist.github.com/55955

Associez cette classe à un simple itérateur ou à une boucle et vous êtes dorés.

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

Votre code est un peu à l'envers, si vous me permettez de le dire. :)

Pourquoi pas:

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

Maintenant , si vous voulez quelque chose comme:

with_spinner do
  # do my big task here
end

... vous devez utiliser le 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

héhé, la réponse ci-dessus la mienne est tout sale.

a=['|','/','-','\\']
a << a
a.each {|item| puts item}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top