简体   繁体   English

与instance_eval的行为不一致

[英]Inconsistent behaviour with instance_eval

When passing a block to instance_eval, it is meant to be executed within the context of that instance. 当将一个块传递给instance_eval时,它应在该实例的上下文中执行。 self , when referenced either explicitly or implicitly within that block, should refer to the instance that instance_eval has been called on. 在该块中显式或隐式引用self时,应引用已调用instance_eval的实例。 This seems to work fine in all cases, except when passing a method object that has been converted to a proc. 这似乎在所有情况下都可以正常工作,除非传递已转换为proc的方法对象。 In this case, self refers to the instance that the method is defined on, rather than the instance where the block is evaluated. 在这种情况下, self指的是定义方法的实例,而不是评估该块的实例。 Here's a code example to demonstrate what I mean: 这是一个代码示例,用以说明我的意思:

class A
  def test(&b)
    instance_eval(&b)
  end
end

class B
  def test_a(a)
    a.test { puts self }
  end

  def test_b_helper(*args)
    puts self
  end

  def test_b(a)
    m = method(:test_b_helper).to_proc
    a.test(&m)
  end
end

a = A.new
b = B.new

b.test_a(a) #<A:0x007ff66b086c68>
b.test_b(a) #<B:0x007fa3e1886bc0>

The expected behaviour is for both tests to return the same output. 两种测试的预期行为是返回相同的输出。 In this case, self should refer to an instance of A, not B. 在这种情况下, 自我应引用A的实例,而不是B。

I have looked in the docs and done some searches, but I have not been able to find information on this peculiarity. 我查看了文档并进行了一些搜索,但是我无法找到有关此特殊性的信息。 I am hoping that there are some experienced Rubyists who can help clear up this difference in behaviour. 我希望有一些经验丰富的Rubyists可以帮助消除这种行为上的差异。

Just to clarify, I am using Ruby 1.9.2. 为了澄清起见,我使用的是Ruby 1.9.2。

The difference is, that Blocks and Procs are closures , Method objects are not. 区别在于,Blocks和Procs是closures ,Method对象不是。

Excerpt from D. Flanagan, Y. Matsumoto. 摘自D. Flanagan,Y。Matsumoto。 The Ruby Programming Language , O'Reilly 2008, p. 《 Ruby编程语言》 ,O'Reilly 2008,第2页。 204: 204:

One important difference between Method objects and Proc objects is that Method objects are not closures. Method对象和Proc对象之间的一个重要区别是Method对象不是闭包。 Ruby's methods are intended to be completely self-contained, and they never have access to local variables outside of their own scope. Ruby的方法旨在完全独立,并且永远无法访问超出其自身范围的局部变量。 The only binding retained by a Method object, therefore, is the value of self — the object on which the method is to be invoked. 因此, Method对象保留的唯一绑定是self的值, self是要在其上调用方法的对象。

When you now cast the Method object to_proc , you bind the value of self to the calling instance of B, hence you get the result you described above. 现在,当将Method对象to_procto_proc self的值绑定到B的调用实例,因此您将获得如上所述的结果。 Actually, self is already fixed when you create the Method object. 实际上,当您创建Method对象时, self已经被修复。

This gets particularly clear when you consider the following code: 当您考虑以下代码时,这一点特别明显:

class A
  def foo
    puts 'bar'
  end
end

class B; end

class C < A; end

foo = A.instance_method(:foo)
# => #<UnboundMethod: A#foo>

a = A.new
foo.bind(a).call
# bar

b = B.new
foo.bind(b).call
# TypeError: bind argument must be an instance of A

c = C.new
foo.bind(c).call
# bar

Simply put: self is always fixed on Method and UnboundMethod objects. 简而言之: self始终固定在MethodUnboundMethod对象上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM