Рубиновая перечисление и return_enumerator - Вопросы относительно внутренних внутренних интервалов Ruby C
-
02-10-2019 - |
Вопрос
Я немного смущен тем, как Руби справляется с созданием перечислений. Итерация на основе блоков имеет смысл и работает для меня; Я все еще запутался, как предполагается возвращение перечислителя по коду.
Вот код, с которым я работаю:
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;
}
Как будет вызвана окончательная строка в цикле Whis в случае перечисления?
Должен ли все мои циклы с циклом проходить до вызовов в return_enumerator (поскольку return_enumerator, по -видимому, должен быть до rb_yield ())?
Что, если я хочу, чтобы что -то произошло, как только внутренняя итерация заканчивается? С блоком я могу просто положить его после петли Whit; Предположительно одинаковые работы в случае перечисления- но как? Кажется, что каждый раз через цикл он возвращает перечислитель, так как же перечислитель узнает, чтобы вернуть соответствующий соответствующий объект? RB_YIELD получает RB_FRAME_HASH в качестве пропущенного ARG, но return_enumerator, похоже, принимает ARG, которые передаются на метод, когда перечисление вызывает метод внутри. Таким образом, ясно, что перечисление вызывает сам метод- возможно, с каким-то внутренним блоком, который просто возвращает экземпляр RB_FRAME_HASH?
Любое понимание внутренних участников ценится.
-Эшер
Решение
Чтобы попытаться ответить на мой собственный вопрос:
Когда называется return_enumerator, называется rb_enumeratorize, который создает перечислитель. Перечисление возвращается; Когда: Далее вызывает перечисление, инициализируется (если необходимо (при необходимости волокно) или возобновляется. Каждый раз: следующее называется, оптоволокно отражает внутренне предоставленный блок один раз, чтобы получить следующий элемент итератора (настройка no_next в структуре C и вызова RB_FIBER_YIELD на волокно перечислителя).
Таким образом, может показаться, что деятельность по петле не должна иметь место до return_enumerator. Я еще не ясно в действиях после перечисления в функции, возвращающем перечисление в случае, когда блок не был предоставлен.