Pregunta

Tengo un método arbitrario en Ruby que los rendimientos de los múltiples valores, por lo que puede ser entregado a un bloque:

def arbitrary
  yield 1
  yield 2
  yield 3
  yield 4
end

arbitrary { |x| puts x }

Me gustaría modificar este método, de modo que, si no hay ningún bloque, sólo devuelve los valores como una matriz.Así que este constructo funcionaría así:

myarray = arbitrary
p a -----> [1, 2, 3, 4, 5]

Es esto posible en Ruby?

¿Fue útil?

Solución

Hay una sintaxis para eso:

def arbitrary(&block)
  values = [1, 2, 3, 4]
  if block
    values.each do |v|
      yield v
    end
  else
    values
  end
end

Nota:

yield v

Se puede reemplazar con:

block.call v

Otros consejos

def arbitrary
  values = [1,2,3,4]
  return values unless block_given? 
  values.each { |val| yield(val) }
end
arbitrary { |x| puts x }
arbitrary

En ruby 1.9+ puede utilizar Enumerador para implementar esto.

def arbitrary(&block)
  Enumerator.new do |y|
    values = [1,2,3,4]
    values.each { |val| y.yield(val) }
  end.each(&block)
end

Tiene la ventaja de que funciona para infinitos arroyos demasiado:

# block-only version
#
def natural_numbers
  0.upto(1/0.0) { |x| yield x }
end

# returning an enumerator when no block is given
#
def natural_numbers(&block)
  Enumerator.new do |y|
    0.upto(1/0.0) { |x| y.yield(x) }
  end.each(&block)
end

Pero la mayoría de los idiomáticas manera de hacerlo es de la guardia de su método con to_enum(your_method_name, your_args) así:

def arbitrary
  return to_enum(:arbitrary) unless block_given?

  yield 1
  yield 2
  yield 3
  yield 4
end

Este es un modismo que ruby núcleo de bibliotecas de uso en varios lugares.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top