Frage

Ich bin ein wenig verwirrt darüber, wie Rubin übernimmt die Erstellung von Enumeratoren. Block-basierte Iteration macht Sinn und arbeitet für mich; Ich bin immer noch verwirrt, wie die Rückkehr eines Enumerator zu Funktionscode weisen soll.

Hier ist der Code, mit denen ich arbeite:

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;
}

Wie würde die letzte Zeile in der while-Schleife im Fall eines Enumerator genannt werden?

Hat alle meine Schleife Aktivität stattfinden müssen, bevor Anrufe RETURN_ENUMERATOR (seit RETURN_ENUMERATOR vermutlich vor rb_yield kommen muss ())?

Was passiert, wenn ich will etwas einmal die interne Iteration beendet passieren? Mit dem Block kann ich sie einfach nach der while-Schleife setzen; vermutlich die gleichen Arbeiten im Falle eines Enumerator- aber wie? Es scheint, wie jedes Mal durch die Schleife es einen Enumerator zurück, so wie funktioniert das Enumerator kennt das entsprechende entsprechende Objekt zurückgeben? rb_yield bekommt rb_frame_hash als bestanden arg, aber RETURN_ENUMERATOR scheint die args zu nehmen, die an die Methode weitergegeben werden, wenn der Enumerator die Methode ruft intern. So klar die Enumerator ist der Aufruf der Methode itself- vielleicht mit einer Art inneren Block, der einfach die Instanz von rb_frame_hash zurückkehrt?

Jeder Einblick in die Interna geschätzt wird.

-Asher

War es hilfreich?

Lösung

Um zu versuchen, meine eigene Frage zu beantworten:

Wenn RETURN_ENUMERATOR genannt wird, rb_enumeratorize genannt wird, die einen Enumerator erstellt. Der Enumerator zurückgegeben; wenn: als nächstes auf dem Enumerator genannt wird, ist eine Faser (falls erforderlich) oder wieder initialisiert. Jedes Mal: ??nächste genannt wird, durchläuft die Faser einen intern bereitgestellt Block einmal um den nächsten Iterator Artikel (Einstellung no_next in dem Enumerator des C-Struktur und rief rb_fiber_yield auf dem Enumerator Fiber) zu erhalten.

So scheint es, dass die Schleife Aktivität nicht vor RETURN_ENUMERATOR nehmen hat. Ich bin noch nicht klar, auf Aktionen nach Auszählung in der Funktion einen Enumerator im Fall der Rückkehr, dass ein Block nicht vorgesehen war.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top