variable valores retornar rangos rails metodos llamar funciones def declarar ruby metaprogramming

rangos - retornar valores en ruby



¿Cómo se pasan los argumentos para definir_method? (4)

Me gustaría pasar un argumento (s) a un método que se define utilizando define_method, ¿cómo lo haría?


... y si quieres parámetros opcionales

class Bar define_method(:foo) do |arg=nil| arg end end a = Bar.new a.foo #=> nil a.foo 1 # => 1

... tantos argumentos como quieras

class Bar define_method(:foo) do |*arg| arg end end a = Bar.new a.foo #=> [] a.foo 1 # => [1] a.foo 1, 2 , ''AAA'' # => [1, 2, ''AAA'']

...combinación de

class Bar define_method(:foo) do |bubla,*arg| p bubla p arg end end a = Bar.new a.foo #=> wrong number of arguments (0 for 1) a.foo 1 # 1 # [] a.foo 1, 2 ,3 ,4 # 1 # [2,3,4]

... todos ellos

class Bar define_method(:foo) do |variable1, variable2,*arg, &block| p variable1 p variable2 p arg p block.inspect end end a = Bar.new a.foo :one, ''two'', :three, 4, 5 do ''six'' end

Actualizar

Ruby 2.0 introdujo doble splat ** (dos estrellas) que ( lo cito ) hace:

Ruby 2.0 introdujo argumentos de palabra clave, y ** actúa como *, pero para argumentos de palabra clave. Devuelve un Hash con pares clave / valor.

... y, por supuesto, también puedes usarlo en el método de definición :)

class Bar define_method(:foo) do |variable1, variable2,*arg,**options, &block| p variable1 p variable2 p arg p options p block.inspect end end a = Bar.new a.foo :one, ''two'', :three, 4, 5, ruby: ''is awesome'', foo: :bar do ''six'' end # :one # "two" # [:three, 4, 5] # {:ruby=>"is awesome", :foo=>:bar}

Ejemplo de atributos con nombre:

class Bar define_method(:foo) do |variable1, color: ''blue'', **other_options, &block| p variable1 p color p other_options p block.inspect end end a = Bar.new a.foo :one, color: ''red'', ruby: ''is awesome'', foo: :bar do ''six'' end # :one # "red" # {:ruby=>"is awesome", :foo=>:bar}

Estaba intentando crear un ejemplo con el argumento de palabras clave, splat y doble splat todo en uno:

define_method(:foo) do |variable1, variable2,*arg, i_will_not: ''work'', **options, &block| # ...

o

define_method(:foo) do |variable1, variable2, i_will_not: ''work'', *arg, **options, &block| # ...

... pero esto no funcionará, parece que hay una limitación. Cuando lo piense, tiene sentido ya que el operador de splat está "capturando todos los argumentos restantes" y double splat está "capturando todos los argumentos de palabra clave restantes", por lo tanto, mezclarlos rompería la lógica esperada. (No tengo ninguna referencia para probar este punto doh!)


Además de la respuesta de Kevin Conner: los argumentos de bloque no admiten la misma semántica que los argumentos de método. No puede definir argumentos predeterminados o argumentos de bloque.

Esto solo se soluciona en Ruby 1.9 con la nueva sintaxis alternativa "stabby lambda" que admite la semántica de argumento de método completo.

Ejemplo:

# Works def meth(default = :foo, *splat, &block) puts ''Bar''; end # Doesn''t work define_method :meth { |default = :foo, *splat, &block| puts ''Bar'' } # This works in Ruby 1.9 (modulo typos, I don''t actually have it installed) define_method :meth, ->(default = :foo, *splat, &block) { puts ''Bar'' }



El bloque que pasas para definir_metodo puede incluir algunos parámetros. Así es como su método definido acepta argumentos. Cuando defines un método, en realidad estás poniendo el sobrenombre al bloque y manteniendo una referencia a él en la clase. Los parámetros vienen con el bloque. Asi que:

define_method(:say_hi) { |other| puts "Hi, " + other }