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

时间:2021-06-22 19:01:45

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一起使用

1 个解决方案

#1


0  

In the second snippet, you are calling m, which returns the result of calling value, which is undefined. (And even if if were somehow magically calling B#value, then B#value returns a String and Strings don't respond to to_proc, so you would get a NoMethodError there.) In the first snippet, you call m, which returns a Proc.

在第二个片段中,您正在调用m,它返回调用value的结果,该结果是未定义的。 (即使如果以某种方式神奇地调用B#值,那么B#值返回一个字符串并且字符串不响应to_proc,所以你会得到一个NoMethodError。)在第一个片段中,你调用m,它返回一个PROC。

It looks like you are trying to pass the method m itself instead of the result of calling it. 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). 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:

看起来你试图传递方法m本身而不是调用它的结果。在Ruby中,方法不是对象,所以你不能只抓住它们并传递它们(即使方法是对象,那么m仍然是调用m的语法,而不是用于引用它)。您必须首先使用Object#方法方法向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. (You may have seen something like foo.map(&:bar) before, which will invoke Symbol#to_proc.)

请注意,对to_proc的调用在这里是完全冗余的,因为如果参数不是Proc已经将调用to_proc。 (您之前可能已经看过类似foo.map(&:bar)的内容,它将调用Symbol#to_proc。)

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

#1


0  

In the second snippet, you are calling m, which returns the result of calling value, which is undefined. (And even if if were somehow magically calling B#value, then B#value returns a String and Strings don't respond to to_proc, so you would get a NoMethodError there.) In the first snippet, you call m, which returns a Proc.

在第二个片段中,您正在调用m,它返回调用value的结果,该结果是未定义的。 (即使如果以某种方式神奇地调用B#值,那么B#值返回一个字符串并且字符串不响应to_proc,所以你会得到一个NoMethodError。)在第一个片段中,你调用m,它返回一个PROC。

It looks like you are trying to pass the method m itself instead of the result of calling it. 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). 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:

看起来你试图传递方法m本身而不是调用它的结果。在Ruby中,方法不是对象,所以你不能只抓住它们并传递它们(即使方法是对象,那么m仍然是调用m的语法,而不是用于引用它)。您必须首先使用Object#方法方法向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. (You may have seen something like foo.map(&:bar) before, which will invoke Symbol#to_proc.)

请注意,对to_proc的调用在这里是完全冗余的,因为如果参数不是Proc已经将调用to_proc。 (您之前可能已经看过类似foo.map(&:bar)的内容,它将调用Symbol#to_proc。)

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