Je suis un peu confus sur la façon dont Ruby gère la création des Enumérateurs. L'itération par bloc a du sens et fonctionne pour moi; Je suis encore confus comment le retour d'un énumérateur est censé fonctionner en code.Ruby Enumeration et RETURN_ENUMERATOR - Questions concernant les Internes C de Ruby
Voici le code, je travaille avec:
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;
}
Comment la dernière ligne dans la boucle while être appelée dans le cas d'un recenseur?
Est-ce que toute mon activité de boucle doit avoir lieu avant les appels à RETURN_ENUMERATOR (puisque RETURN_ENUMERATOR doit probablement précéder rb_yield())? Et si je veux que quelque chose se produise une fois l'itération interne terminée? Avec le bloc je peux simplement le mettre après la boucle while; probablement les mêmes travaux dans le cas d'un énumérateur - mais comment? Il semble que chaque fois que la boucle retourne un énumérateur, comment l'énumérateur sait-il renvoyer l'objet correspondant? rb_yield obtient rb_frame_hash comme argument passé, mais RETURN_ENUMERATOR semble prendre les arguments qui sont relayés à la méthode lorsque l'énumérateur appelle la méthode en interne. Il est donc clair que l'Enumérateur appelle la méthode elle-même - peut-être avec un type de bloc interne qui renvoie simplement l'instance de rb_frame_hash?
Tout aperçu des composants internes est apprécié.
-Asher