代码之家  ›  专栏  ›  技术社区  ›  Asher postmodern

Ruby枚举和返回枚举器-关于Ruby C内部的问题

  •  0
  • Asher postmodern  · 技术社区  · 14 年前

    我对Ruby如何处理枚举器的创建有点困惑。基于块的迭代是有意义的,并且对我来说是有效的;我仍然困惑于枚举器的返回应该如何以代码的方式运行。

    下面是我正在处理的代码:

    VALUE rb_RPRuby_Sender_Kernel_each_backtrace_frame( int      argc,
                                                           VALUE*   args,
                                                           VALUE    rb_self )   {
    
        rb_thread_t*            c_thread  = GET_THREAD();
        //  Get the current frame - we're doing a backtrace, so our current working frame to start is the first previous thread
        rb_control_frame_t*     c_current_context_frame    = RUBY_VM_PREVIOUS_CONTROL_FRAME( RUBY_VM_PREVIOUS_CONTROL_FRAME( c_thread->cfp ) );
    
        //  c_top_of_control_frame describes the top edge of the stack trace
        //  set c_top_of_control_frame to the first frame in <main>
        rb_control_frame_t*     c_top_of_control_frame  =   RUBY_VM_NEXT_CONTROL_FRAME( RUBY_VM_NEXT_CONTROL_FRAME( (void *)( c_thread->stack + c_thread->stack_size ) ) );
    
        //  for each control frame:
        while ( c_current_context_frame < c_top_of_control_frame ) {
    
            VALUE   rb_frame_hash   =   rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame(  & c_current_context_frame );
    
            //  if we don't have a block, return enumerator
            RETURN_ENUMERATOR( rb_self, 0, NULL );
    
            //  otherwise, yield the block
            rb_yield( rb_frame_hash );
    
            c_current_context_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( c_current_context_frame );        
        }
    
        return Qnil;
    }
    

    对于枚举器,如何调用while循环中的最后一行?

    是否所有循环活动都必须在调用返回_枚举器之前发生(因为返回_枚举器可能必须在rb_yield()之前发生)?

    如果我希望在内部迭代完成后发生什么呢?对于这个块,我可以简单地将它放在while循环之后;对于枚举器,可能也是这样——但是如何处理呢?似乎每次通过循环它都会返回一个枚举器,那么枚举器如何知道返回适当的对应对象呢?rb_yield将rb_frame_hash作为传递的参数获取,但返回的_枚举器似乎接受在枚举器内部调用方法时中继到方法的参数。那么显然枚举器正在调用方法本身——也许是使用某种只返回rb-frame-hash实例的内部块?

    任何对内部的洞察都是值得赞赏的。

    -亚瑟

    1 回复  |  直到 14 年前
        1
  •  0
  •   Asher postmodern    14 年前

    试图回答我自己的问题:

    当调用返回枚举器时,将调用rb_Enumeratorize,这将创建一个枚举器。返回枚举器;在枚举器上调用:Next时,将初始化(如有必要)或恢复光纤。每次调用:next时,fiber迭代一次内部提供的块,以获取下一个迭代器项(在枚举器的C结构中设置no_next,并在枚举器的fiber上调用rb_fiber_yield)。

    因此,循环活动似乎不必在返回枚举器之前发生。我还不清楚在没有提供块的情况下返回枚举器的函数中枚举后的操作。