ventajas tutorial sirve rails que para documentacion desventajas descargar ruby

ruby - tutorial - ¿Es ''el rendimiento propio'' lo mismo que instance_eval?



ruby wikipedia (3)

Ellos son diferentes. yield(self) no cambia el valor de self dentro del bloque, mientras que instance_eval(&block) sí lo hace.

class Foo def with_yield yield(self) end def with_instance_eval(&block) instance_eval(&block) end end f = Foo.new f.with_yield do |arg| p self # => main p arg # => #<Foo:0x100124b10> end f.with_instance_eval do |arg| p self # => #<Foo:0x100124b10> p arg # => #<Foo:0x100124b10> end

¿Hay alguna diferencia si define Foo con instance_eval:. . .

class Foo def initialize(&block) instance_eval(&block) if block_given? end end

. . . o con ''auto rendirse'':

class Foo def initialize yield self if block_given? end end

En cualquier caso puedes hacer esto:

x = Foo.new { def foo; ''foo''; end } x.foo

Por lo tanto, " yield self " significa que el bloque después de Foo.new siempre se evalúa en el contexto de la clase Foo.

¿Es esto correcto?


Solo puedes soltar la palabra clave

class Foo def initialize yield if block_given? end end

Actualización de comentarios

Usar el rendimiento es un poco nuevo para mi gusto, especialmente cuando se usa fuera de irb.

Sin embargo, hay una gran diferencia significativa entre el enfoque de instance_eval y el enfoque de rendimiento , verifique este fragmento de código:

class Foo def initialize(&block) instance_eval(&block) if block_given? end end x = Foo.new { def foo; ''foo''; end } #=> #<Foo:0xb800f6a0> x.foo #=> "foo" z = Foo.new #=> #<Foo:0xb800806c> z.foo #=>NoMethodError: undefined method `foo'' for #<Foo:0xb800806c>

Marque este también:

class Foo2 def initialize yield if block_given? end end x = Foo2.new { def foo; ''foo''; end } #=> #<Foo:0xb7ff1bb4> x.foo #=> private method `foo'' called for #<Foo2:0xb8004930> (NoMethodError) x.send :foo => "foo" z = Foo.new #=> #<Foo:0xb800806c> z.send :foo => "foo"

Como puede ver, la diferencia es que el primero está agregando un método singleton foo al objeto que se está inicializando, mientras que el último está agregando un método privado a todas las instancias de la clase Object.


Tus dos piezas de código hacen cosas muy diferentes. Al utilizar instance_eval, está evaluando el bloque en el contexto de su objeto. Esto significa que usar def definirá métodos en ese objeto. También significa que llamar a un método sin un receptor dentro del bloque lo llamará a su objeto.

Cuando te entregas a ti mismo, te estás pasando como un argumento al bloque, pero como tu bloque no acepta ningún argumento, simplemente se ignora. Entonces, en este caso, rendirse a uno mismo hace lo mismo que no producir nada. La def aquí se comporta exactamente como lo haría una def fuera del bloque, produciendo self no cambia realmente lo que define el método. Lo que podrías hacer es:

class Foo def initialize yield self if block_given? end end x = Foo.new {|obj| def obj.foo() ''foo'' end} x.foo

La diferencia con instance_eval es que tiene que especificar explícitamente el receptor.

Editar para aclarar:

En la versión con rendimiento, obj en el bloque será el objeto que se produce, que en este caso es la instancia de Foo recién creada. Mientras que uno mismo tendrá el mismo valor que tenía fuera del bloque. Con la versión instance_eval self dentro del bloque será la instancia de Foo recién creada.