Ruby - define_method and closures

define_method exhibits the following behavior:

class TestClass
  def exec_block(&block) ; yield ; end
end
TestClass.new.send(:exec_block) do ; puts self ; end
# -> main
TestClass.send(:define_method, :bing) do ; puts self ; end
TestClass.new.bing
# -> <TestClass:...>

I do not understand that the block passed to define_method should be a closure. As such, it should be (at least according to my understanding) to fix the value of selfboth main, as shown in the call exec_block.

I understand that the block will become the body of the method, but I do not understand the reason for the behavior. Why does a block evaluate different things when used with different methods?

How can I reproduce the behavior of a block using define_methodfor other methods? for example, how do you write exec_blockit to output <TestClass:...>instead of `main '?

+3
source share
3 answers

self . , , Proc :

class A
  def exec_block(&block)
    block.call
  end
end

class B
  def exec_indirect(&block)
    A.new.exec_block(&block)
  end
end

block = proc { p self }
a = A.new; b = B.new

a.exec_block(&block)    # => main
b.exec_indirect(&block) # => main

BasicObject#instance_eval alikes self:

, self obj , objs

Module#define_method instance_eval :

, . instance_eval [...]

:

A.send(:define_method, :foo, &block)
a.foo                   # => #<A:0x00000001717040>
a.instance_eval(&block) # => #<A:0x00000001717040>

exec_block instance_eval:

class A
  def exec_block(&block)
    instance_eval(&block)
  end
end

block = proc { p self }
A.new.exec_block(&block)  # => #<A:0x00000001bb9828>

, instance_eval Proc . Ruby.

+5

- yield, block.call. - exec_block yield instance_eval(&block), ;)

- self, main.

( define_method) , instance_eval. : http://apidock.com/ruby/Module/define_method

0

Inspired by a comment by Niklas B .:

class TestClass
  def exec_block(&block) ; yield ; end
end
s = self

TestClass.new.send(:exec_block) do ; puts s ; end
# -> main

TestClass.send(:define_method, :bing) do ; puts s ; end
TestClass.new.bing
# -> main
0
source

All Articles