Kernel#loop returns the result value of a finished iterator
* vm_eval.c (rb_f_loop): When a loop is stopped by a StopIteration exception, return what the enumerator has returned instead of nil. [ruby-core:71133] [Feature #11498] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52218 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
53d6e605b0
commit
f4c487173c
@ -1,3 +1,9 @@
|
|||||||
|
Thu Oct 22 18:52:53 2015 Akinori MUSHA <knu@iDaemons.org>
|
||||||
|
|
||||||
|
* vm_eval.c (rb_f_loop): When a loop is stopped by a StopIteration
|
||||||
|
exception, return what the enumerator has returned instead of
|
||||||
|
nil. [ruby-core:71133] [Feature #11498]
|
||||||
|
|
||||||
Thu Oct 22 18:25:10 2015 Shugo Maeda <shugo@ruby-lang.org>
|
Thu Oct 22 18:25:10 2015 Shugo Maeda <shugo@ruby-lang.org>
|
||||||
|
|
||||||
* lib/net/imap (idle): add a new argument timeout for keep-alive.
|
* lib/net/imap (idle): add a new argument timeout for keep-alive.
|
||||||
|
5
NEWS
5
NEWS
@ -64,6 +64,11 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
this parameter is bitwise-ORed to oflags generated by normal mode argument.
|
this parameter is bitwise-ORed to oflags generated by normal mode argument.
|
||||||
[Feature #11253]
|
[Feature #11253]
|
||||||
|
|
||||||
|
* Kernel
|
||||||
|
|
||||||
|
* Kernel#loop, when stopped by a StopIteration exception, returns
|
||||||
|
what the enumerator has returned instead of nil.
|
||||||
|
|
||||||
* Module
|
* Module
|
||||||
* Module#deprecate_constant [Feature #11398]
|
* Module#deprecate_constant [Feature #11398]
|
||||||
|
|
||||||
|
@ -46,6 +46,14 @@ class TestEnumerator < Test::Unit::TestCase
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_loop_return_value
|
||||||
|
assert_equal nil, loop { break }
|
||||||
|
assert_equal 42, loop { break 42 }
|
||||||
|
|
||||||
|
e = Enumerator.new { |y| y << 1; y << 2; :stopped }
|
||||||
|
assert_equal :stopped, loop { e.next while true }
|
||||||
|
end
|
||||||
|
|
||||||
def test_nested_iteration
|
def test_nested_iteration
|
||||||
def (o = Object.new).each
|
def (o = Object.new).each
|
||||||
yield :ok1
|
yield :ok1
|
||||||
|
25
vm_eval.c
25
vm_eval.c
@ -24,7 +24,7 @@ static void vm_set_eval_stack(rb_thread_t * th, const rb_iseq_t *iseq, const rb_
|
|||||||
static int vm_collect_local_variables_in_heap(rb_thread_t *th, const VALUE *dfp, const struct local_var_list *vars);
|
static int vm_collect_local_variables_in_heap(rb_thread_t *th, const VALUE *dfp, const struct local_var_list *vars);
|
||||||
|
|
||||||
static VALUE rb_eUncaughtThrow;
|
static VALUE rb_eUncaughtThrow;
|
||||||
static ID id_tag, id_value;
|
static ID id_result, id_tag, id_value;
|
||||||
#define id_mesg idMesg
|
#define id_mesg idMesg
|
||||||
|
|
||||||
/* vm_backtrace.c */
|
/* vm_backtrace.c */
|
||||||
@ -1078,6 +1078,12 @@ loop_i(void)
|
|||||||
return Qnil;
|
return Qnil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VALUE
|
||||||
|
loop_stop(VALUE dummy, VALUE exc)
|
||||||
|
{
|
||||||
|
return rb_attr_get(exc, id_result);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
|
rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
|
||||||
{
|
{
|
||||||
@ -1100,15 +1106,25 @@ rb_f_loop_size(VALUE self, VALUE args, VALUE eobj)
|
|||||||
* # ...
|
* # ...
|
||||||
* end
|
* end
|
||||||
*
|
*
|
||||||
* StopIteration raised in the block breaks the loop.
|
* StopIteration raised in the block breaks the loop. In this case,
|
||||||
|
* loop returns the "result" value stored in the exception.
|
||||||
|
*
|
||||||
|
* enum = Enumerator.new { |y|
|
||||||
|
* y << "one"
|
||||||
|
* y << "two"
|
||||||
|
* :ok
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* result = loop {
|
||||||
|
* puts enum.next
|
||||||
|
* } #=> :ok
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
rb_f_loop(VALUE self)
|
rb_f_loop(VALUE self)
|
||||||
{
|
{
|
||||||
RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size);
|
RETURN_SIZED_ENUMERATOR(self, 0, 0, rb_f_loop_size);
|
||||||
rb_rescue2(loop_i, (VALUE)0, 0, 0, rb_eStopIteration, (VALUE)0);
|
return rb_rescue2(loop_i, (VALUE)0, loop_stop, (VALUE)0, rb_eStopIteration, (VALUE)0);
|
||||||
return Qnil; /* dummy */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if VMDEBUG
|
#if VMDEBUG
|
||||||
@ -2184,6 +2200,7 @@ Init_vm_eval(void)
|
|||||||
rb_define_method(rb_eUncaughtThrow, "value", uncaught_throw_value, 0);
|
rb_define_method(rb_eUncaughtThrow, "value", uncaught_throw_value, 0);
|
||||||
rb_define_method(rb_eUncaughtThrow, "to_s", uncaught_throw_to_s, 0);
|
rb_define_method(rb_eUncaughtThrow, "to_s", uncaught_throw_to_s, 0);
|
||||||
|
|
||||||
|
id_result = rb_intern_const("result");
|
||||||
id_tag = rb_intern_const("tag");
|
id_tag = rb_intern_const("tag");
|
||||||
id_value = rb_intern_const("value");
|
id_value = rb_intern_const("value");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user