Ruby 块作用域 instance_eval
Ruby Block Scope with instance_eval
我对 Ruby 块和过程的理解是它们都是闭包。既然我已经看到它与 instance_eval 一起使用,我有点困惑。与 instance_eval 相比,在最常见的使用情况下,改变块范围在最常见用途下的行为方式是什么神奇酱料,在查看裸机时的底层工作原理?
这是一个示例,您可以在 IRB 中转储以了解我的意思。我已经包含了 proc.call 和块收益版本示例。令人高兴的是,他们的行为方式相同。
# Testing block/proc and eval
class Example
def initialize(value)
# value defined in the instance
@value = value
end
def call_a_proc(proc)
proc.call self
end
def yield_to_block
yield self
end
end
# Value defined in the global object
@value = 1
example = Example.new 'a'
# the block/proc that prints @value
proc1 = -> instance { puts @value }
# instance calling/yielding the block/proc that prints @value
proc2 = -> instance { instance.call_a_proc proc1 }
proc3 = -> instance { instance.yield_to_block &proc1 }
# instance_eval of the block that prints @value
proc4 = -> instance { instance.instance_eval &proc1 }
# the block/proc reference @value from the global context, the context in which it was defined (standard closure)
example.call_a_proc proc1
example.yield_to_block &proc1
example.call_a_proc proc2
example.yield_to_block &proc2
example.call_a_proc proc3
example.yield_to_block &proc3
# block/proc has it's context redefined as coming from within the instance.
example.call_a_proc proc4
example.yield_to_block &proc4
我知道这是 instance_eval 方法的要点,我只是不确定它是如何工作的。
当您在词法作用域(您的主源文件)中定义 @value
时,您是在全局解释器中定义一个实例变量。例如:
self #=> main
# "self" here refers to the main interpreter, which is of class Object
self.instance_variable_get(:@value) #=> 1
# "example" is your instance above
example.instance_variable_get(:@value) #=> "a"
# "self" has been changed to refer to "example" using instance_eval
example.instance_eval { self.instance_variable_get(:@value) } #=> "a"
# this syntax is just a shortcut for the line above
example.instance_eval { @value } #=> "a"
使用 instance_eval
,您所做的只是将主解释器 self
替换为您在 instance_eval
上调用的对象。
我对 Ruby 块和过程的理解是它们都是闭包。既然我已经看到它与 instance_eval 一起使用,我有点困惑。与 instance_eval 相比,在最常见的使用情况下,改变块范围在最常见用途下的行为方式是什么神奇酱料,在查看裸机时的底层工作原理?
这是一个示例,您可以在 IRB 中转储以了解我的意思。我已经包含了 proc.call 和块收益版本示例。令人高兴的是,他们的行为方式相同。
# Testing block/proc and eval
class Example
def initialize(value)
# value defined in the instance
@value = value
end
def call_a_proc(proc)
proc.call self
end
def yield_to_block
yield self
end
end
# Value defined in the global object
@value = 1
example = Example.new 'a'
# the block/proc that prints @value
proc1 = -> instance { puts @value }
# instance calling/yielding the block/proc that prints @value
proc2 = -> instance { instance.call_a_proc proc1 }
proc3 = -> instance { instance.yield_to_block &proc1 }
# instance_eval of the block that prints @value
proc4 = -> instance { instance.instance_eval &proc1 }
# the block/proc reference @value from the global context, the context in which it was defined (standard closure)
example.call_a_proc proc1
example.yield_to_block &proc1
example.call_a_proc proc2
example.yield_to_block &proc2
example.call_a_proc proc3
example.yield_to_block &proc3
# block/proc has it's context redefined as coming from within the instance.
example.call_a_proc proc4
example.yield_to_block &proc4
我知道这是 instance_eval 方法的要点,我只是不确定它是如何工作的。
当您在词法作用域(您的主源文件)中定义 @value
时,您是在全局解释器中定义一个实例变量。例如:
self #=> main
# "self" here refers to the main interpreter, which is of class Object
self.instance_variable_get(:@value) #=> 1
# "example" is your instance above
example.instance_variable_get(:@value) #=> "a"
# "self" has been changed to refer to "example" using instance_eval
example.instance_eval { self.instance_variable_get(:@value) } #=> "a"
# this syntax is just a shortcut for the line above
example.instance_eval { @value } #=> "a"
使用 instance_eval
,您所做的只是将主解释器 self
替换为您在 instance_eval
上调用的对象。