简体   繁体   English

为什么在使用to_proc而不是Proc.new调用instance_eval时出现错误?

[英]Why am I getting an error calling instance_eval with to_proc and not with Proc.new?

I'm doing this and it works: 我正在这样做,它的工作原理是:

class B
  def value
    "X"
  end
end

class A
  def initialize(context)
    @context = context
  end

  def m
    Proc.new do
      value
    end
  end

  def execute
    @context.instance_eval(&m)
  end
end

A.new(B.new).execute #=> "X"

But calling m.to_proc is not working... 但是调用m.to_proc无法正常工作...

class B
  def value
    "X"
  end
end

class A
  def initialize(context)
    @context = context
  end

  def m
    value
  end

  def execute
    @context.instance_eval(&m.to_proc)
  end
end

A.new(B.new).execute #=> NameError: undefined local variable or method `value' for #<A:0x007fae2ab02040 @context=#<B:0x007fae2ab02108>>

I want to know why these two examples are different and how to make it work with to_proc 我想知道这两个示例为何不同,以及如何使其与to_proc

In the second snippet, you are calling m , which returns the result of calling value , which is undefined. 在第二个片段中,您正在调用m ,该value返回未定义的调用value的结果。 (And even if if were somehow magically calling B#value , then B#value returns a String and String s don't respond to to_proc , so you would get a NoMethodError there.) In the first snippet, you call m , which returns a Proc . 即使如果不知何故神奇地调用B#value ,则B#value返回一个StringString ■不要回应to_proc ,所以你会得到一个NoMethodError那里。)在第一个片段,你叫m ,它返回一个Proc

It looks like you are trying to pass the method m itself instead of the result of calling it. 看起来您正在尝试传递方法m 本身,而不是调用它的结果。 In Ruby, methods aren't objects, so you can't just grab them and pass them around (and even if methods were objects, then m is still the syntax for calling m , not for referencing it). 在Ruby中,方法不是对象,所以您不能只是抓住它们并传递它们(即使方法是对象,那么m仍然是调用m的语法,而不是引用它的语法)。 You have to ask Ruby's reflection API for a reflective proxy for the method first, using the Object#method method, which returns a Method object representing the method: 您必须首先使用Object#method方法向Ruby的反射API请求该方法的反射代理,该方法返回代表该方法的Method对象:

@context.instance_eval(&method(:m).to_proc)

Note that the call to to_proc is completely redundant here, since & will call to_proc anyway if the argument isn't a Proc already. 注意,这里对to_proc的调用是完全多余的,因为如果参数还不是Proc ,则&仍然会调用to_proc (You may have seen something like foo.map(&:bar) before, which will invoke Symbol#to_proc .) (您之前可能已经看过类似foo.map(&:bar)东西,它将调用Symbol#to_proc 。)

@context.instance_eval(&method(:m))

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

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