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...
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
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 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
.
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:
@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
.)
@context.instance_eval(&method(:m))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.