ruby metaprogramming

Usando el rendimiento dentro de define_method en Ruby



metaprogramming (2)

¿Es posible hacer que la palabra clave de rendimiento funcione dentro de un bloque dado a define_method? Ejemplo simple:

class Test define_method :test do |&b| puts b # => #<Proc:...> yield end end Test.new.test { puts "Hi!" }

Este código produce el siguiente error en Ruby 1.8.7 y 1.9.0:

test.rb: 4: en `test '': no ​​se proporcionó ningún bloque (LocalJumpError) desde test.rb: 8

Lo extraño es la variable del bloque b != nil block_given? pero block_given? devuelve falso. ¿Es el comportamiento de Ruby intencional no reconocer bloques por objetos Proc ?

Edición: Saludos a la respuesta de b.call() : b.call() no es lo que estoy buscando. La variable de bloque se usó solo para indicar que el bloque realmente se da y no se detecta dentro de define_method.

Por lo que necesito usar yield lugar de block.call

Estoy dispuesto a escribir alguna extensión sobre la forma en que se definen las nuevas clases en Ruby, por lo tanto, cualquier código que pueda escribir en Ruby puro debe ser aceptado cuando uso mi extensión.

Por lo tanto, no se puede tener en cuenta una semántica similar, ya que esto obliga a los usuarios de mi biblioteca a usar solo una forma adecuada de pasar un bloque. Esto rompe la regla TIMTOWTDI y no hace que mi biblioteca sea transparente.

Ejemplo de la vida real

El código a continuación se puede simplificar al código anterior ya que my_def usa define_method :

require ''my_library'' class Test # client can write ''my_def'' instead of ''def'' since # my_library extends Class class my_def :test, "some parameter" do yield # oh no, error :( end end Test.new.test { puts "Hi!" }



No puedes usar el yield dentro de un bloque define_method . Esto se debe a que los bloques son capturados por cierres, observe:

def hello define_singleton_method(:bye) { yield } end hello { puts "hello!" } bye { puts "bye!" } #=> "hello!"

No creo que a sus usuarios les importe no poder utilizar el ''rendimiento'' de la forma en que usted lo expresa: la sintaxis no se parece en nada a la sintaxis de definición del método Ruby, por lo que es poco probable que haya confusión.

Más información sobre por qué no puede pasar bloques implícitamente a los métodos que se encuentran aquí: http://banisterfiend.wordpress.com/2010/11/06/behavior-of-yield-in-define_method/