Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Ruby:如何通过instance_eval运行这个块?_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails Ruby:如何通过instance_eval运行这个块?

Ruby on rails Ruby:如何通过instance_eval运行这个块?,ruby-on-rails,ruby,Ruby On Rails,Ruby,我最近看到了一些我不完全理解的代码。有一个名为foo的数组,其中包含Proc对象的实例。然后,使用环境对象设置要在其中工作的环境: env = Object.new foo.each do |f| env.instance_eval &f # what happens here? end 使用instance_eval打开对象并将&f作为参数传递时,会发生什么情况?此时env和Proc本身会发生什么情况?Proc的作用域会更改,然后在该上下文中对其进行评估。在内部,所有proc

我最近看到了一些我不完全理解的代码。有一个名为
foo
的数组,其中包含
Proc
对象的实例。然后,使用环境对象设置要在其中工作的环境:

env = Object.new
foo.each do |f|
    env.instance_eval &f # what happens here?
end

使用instance_eval打开对象并将
&f
作为参数传递时,会发生什么情况?此时env和Proc本身会发生什么情况?

Proc的作用域会更改,然后在该上下文中对其进行评估。在内部,所有proc都以C
struct
的形式存储在内存中,其中包括proc的
self
(生成proc的范围)。调用
instance\u eval
时,会在内存中将
self
值手动更改为正在调用
instance\u eval
的对象。如果您浏览ruby源代码,您会发现它可以归结为以下函数:

static VALUE
yield_under(VALUE under, VALUE self, VALUE values)
{
    rb_thread_t *th = GET_THREAD();
    rb_block_t block, *blockptr;
    NODE *cref;

    if ((blockptr = GC_GUARDED_PTR_REF(th->cfp->lfp[0])) != 0) {
    block = *blockptr;
    block.self = self; // <- This is where the scope changes!
    th->cfp->lfp[0] = GC_GUARDED_PTR(&block);
    }
    cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);
    cref->flags |= NODE_FL_CREF_PUSHED_BY_EVAL;

    if (values == Qundef) {
    return vm_yield_with_cref(th, 1, &self, cref);
    }
    else {
    return vm_yield_with_cref(th, RARRAY_LENINT(values), RARRAY_PTR(values), cref);
    }
}
静态值
收益率(低于价值、自身价值、价值)
{
rb_thread_t*th=GET_thread();
rb_block_t block,*blockptr;
节点*cref;
如果((blockptr=GC_-GUARDED_-PTR_-REF(th->cfp->lfp[0]))!=0){
block=*blockptr;
block.self=self;//cfp->lfp[0]=GC\u-GUARDED\u-PTR(&block);
}
cref=vm_cref_push(th,under,NOEX_PUBLIC,blockptr);
cref->flags |=节点_FL _cref _由_EVAL推送_;
如果(值==Qundef){
返回带有cref(th,1和self,cref)的vm\u yield\u;
}
否则{
返回vm_yield_和cref(th,RARRAY_lent(值),RARRAY_PTR(值),cref);
}
}

注意,包含
/的行在
env
的上下文中执行Proc。这就好像您在
env
上调用一个方法:该块可以访问其实例变量以及公共和私有方法

env = Object.new

env.instance_variable_set :@test, "test"

class << env
  private
  def test
    @test
  end
end

env.instance_eval { @test } #=> "test"
env.instance_eval { test }  #=> "test"
env=Object.new
env.instance_variable_set:@test,“test”
“测试”类
env.instance_eval{test}#=>“test”