Pregunta

Estoy tratando de aprender algo de rubí. Imagina que estoy haciendo un bucle y haciendo un proceso de larga duración, y en este proceso quiero obtener una ruleta durante el tiempo que sea necesario.

Entonces podría hacer:

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"

Pero pensé que sería más limpio hacer:

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

Por supuesto, la llamada spinChar quiere un bloqueo. Si le doy un bloque, se colgará indefinidamente.

¿Cómo puedo obtener solo el próximo año de este bloque?

¿Fue útil?

Solución

Ruby yield no funciona en como le gustaría a su ejemplo. Pero este podría ser un buen lugar para un cierre :

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 la práctica, creo que esta solución podría ser demasiado inteligente " " por su propio bien, pero entendiendo la idea de Proc s podría ser útil de todos modos.

Otros consejos

Me gustan todas estas sugerencias, pero encontré el generador en la biblioteca estándar, y creo que es más parecido a lo que quería hacer:

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

incrementos de índice de matriz con módulo en una matriz congelada parecen ser los más rápidos.

El hilo de Vlad es ingenioso pero no es exactamente lo que quería. Y en class spinner el incremento de una línea sería mejor si Ruby apoyara i ++ como GLYPHS [@i ++% GLYPHS.length]

El

cierre de spinner Max con push shift me parece un poco intenso, pero la sintaxis resultante es casi exactamente como este generador. Al menos creo que eso es un cierre con proc.

El with_spinner de Chuck en realidad es bastante parecido a lo que quería, pero ¿por qué romper si no tiene que hacerlo con un generador como el anterior?

Vadim, gracias por señalar que el generador sería lento.

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

Creo que estabas en el camino correcto con cycle . ¿Qué tal algo como esto?

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

No creo que entiendas lo que hace yield en Ruby. No devuelve un valor de un bloque & # 8212; pasa un valor a el bloque que ha pasado al método de cierre.

Creo que quieres algo más como esto:

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

Érase una vez, escribí una matriz. Pero no es solo una matriz, es una matriz que tiene un puntero, ¡así que puedes llamar a nextr para siempre! http://gist.github.com/55955

Combina esta clase con un simple iterador o bucle y estarás dorado.

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

Su código está un poco al revés, si me perdona decirlo. :)

¿Por qué no?

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

Ahora , si quieres algo como:

with_spinner do
  # do my big task here
end

... entonces tendría que usar subprocesos múltiples :

def with_spinner
  t = Thread.new do
    ['|','/','-','\\'].cycle { |c| print "#{c}\b" ; sleep(1) }
  end
  yield
  Thread.kill(t) # nasty but effective
end

jeje, la respuesta sobre la mía está toda sucia.

a=['|','/','-','\\']
a << a
a.each {|item| puts item}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top