Enumerator#peek e$B$r?7@_$9$k$N$O$I$&$G$7$g$&$+!#e(B
Enumerator
e$B$+$i%G!<%?$rFI$=P$9$H$-!"@hFI$$r$7$?$/$J$k$3$H$,$"$j$^$9!#e(B
e$B$?$H$($P!"%=!<%H:Q$_$NC18l$NNs$,$"$C$?$H$-$K!"3FC18l$N?t$r5ae(B
e$B$a$?$$$H$9$k$H!"0J2<$N$h$&$K<!$NMWAG$H$NHf3S$r$7$?$/$J$j$^$9!#e(B
a = %w[banana banana durian orange orange orange]
e = a.to_enum
n = 0
loop {
word = e.next
n += 1
if e$B<!$NMWAG$,B8:$7$Fe(B word e$B$H$O0[$J$k$+!"B8:$7$J$$e(B
puts “#{word} #{n}”
word = nil
n = 0
end
}
e$B$7$+$7!"$3$3$Ge(B Enumerator#next
e$B$O;H$($^$;$s!#;H$C$F$7$^$&$H!"e(B
e$B%k!<%W$N<!$N2s$G07$&$Y$-MWAG$r>CHq$7$F$7$^$$$^$9!#e(B
e$B$+$H$$$C$F!"%k!<%W$N<!$N2s$G=hM}$9$k$h$&$K$9$k$H!"%k!<%W$N$Re(B
e$B$H$^$o$j$4$H$K$R$H$D$NMWAG$r=hM}$9$k$H$$$&9=B$$,2u$l$F$o$+$je(B
e$B$K$/$/$J$j$^$9!#$^$?!":G8e$NC18l$N=hM}$r%k!<%W$,=*$o$C$?8e$Ke(B
e$B$9$k$3$H$K$J$C$F!"3FC18lKh$K9T$&=hM}$,%k!<%W$NCf$H8e$K$U$?$De(B
e$BI,MW$K$J$C$F$7$^$$$^$9!#$?$H$($P!"0J2<$N$h$&$K=q$1$^$9$,!“e(B
e$B%3!<%I$N=EJ#$,@8$8!”$^$?Fq$7$/$J$C$F$$$^$9!#e(B
% ./ruby -e ’
a = %w[banana banana durian orange orange orange]
e = a.to_enum
n = 0
prev = nil
loop {
word = e.next
if prev && prev != word
puts “#{prev} #{n}”
n = 0
end
prev = word
n += 1
}
if prev
puts “#{prev} #{n}”
end
’
banana 2
durian 1
orange 3
e$B31$5$s$NH/I=$GCN$C$?$s$G$9$,!"$3!<$f!<$N$C$F%3%s%H%m!<%k%Ve(B
e$B%l!<%/$C$F$$$&$s$G$9$M!#e(B
e$B$=$3$G!“MWAG$r>CHq$;$:$KFI$=P$9!"$D$^$j@hFI$$r$9$k%a%=%C%Ie(B
e$B$,$”$l$P!":G=i$K=q$$$?!"%k!<%W$N$R$H$^$o$j$4$H$K$R$H$D$NMWAGe(B
e$B$r=hM}$9$k$H$$$&7A$G5-=R$G$-$^$9!#$=$&$$$&%a%=%C%I$re(B
Enumerator#peek e$B$H$9$k$H!"0J2<$N$h$&$K=q$1$^$9!#e(B
% ./ruby -e ’
a = %w[banana banana durian orange orange orange]
e = a.to_enum
n = 0
loop {
word = e.next
n += 1
if begin word != e.peek; rescue StopIteration; true end
puts “#{word} #{n}”
word = nil
n = 0
end
}
’
banana 2
durian 1
orange 3
e$B$^$!!"e(Brescue e$B$9$k$N$O8+6l$7$$$N$G!"0z?t$r;XDj$7$?$ie(B
StopIteration e$BNc30$N$+$o$j$K0z?t$rJV$9$h$&$K$7$?$i$$$$$+$J!“e(B
e$B$J$I$H$$$&$3$H$b9M$($i$l$^$9$,!“4pK\E*$J%”%$%G%”$H$7$F$O$I$&e(B
e$B$G$7$g$&$+!#e(B
e$B$3$3$G!“MWAG$NJB$S$+$i$3$&$d$C$F>pJs$r$^$H$a$F$$$/$H$$$&$N$O!“e(B
%w[banana banana durian orange orange orange]
e$B$H$$$&J?C3$J9=B$$+$ie(B
[%w[banana banana], %w[durian], %w[orange orange orange]]
e$B$H$$$&LZ9=B$$r9=@.$9$k9=J82r@O$H$b$$J$;$^$9$N$G!"@hFI$$,I,e(B
e$BMW$K$J$k$H$$$&$N$O$h$/$”$k$b$N$G$”$k$HA[Dj$G$-$^$9!#$=$7$F!“e(B
e$B9=J82r@O$+$i$NN?d$H$7$F!"@hFI$_$O$R$H$D$G:Q$
$3$H$,B?$$!”$He(B
e$B$$$&$3$H$bM=A[$G$-$^$9!#$D$^$je(B Enumerable#peek e$B$O$R$H$D$N@he(B
e$BFI$$rDs6!$9$k$3$H$+$i!"$h$/$"$k>u67$KBP1~$G$-!"$+$D!"$3$l$he(B
e$B$je(B (e$BJ#?t$N@hFI$$rDs6!$9$k$h$&$Je(B)
e$B0lHL2=$7$F$b$=$l$[$I1W$O$Je(B
e$B$$!"$H$$$&;EMM$K$J$C$F$$$k$H$$$($k$N$G$O$J$$$G$7$g$&$+!#e(B
e$B$J$*!"$A$g$C$H$7$?I{:nMQ$H$7$F!"e(BStopIteration
e$B$,H/@8$7$?8e$K!"e(B
Enumerator#next e$B$r8F$s$@;~!“e(B(e$B7+$jJV$7$N:G=i$KLa$k$N$G$O$J$/e(B)
e$B$:$C$He(B StopIteration e$B$,H/@8$9$k$h$&$KJQ$($F$”$j$^$9!#e(B
e$B$3$l$O!“0J2<$N$h$&$JM}M3$,$”$j$^$9!#e(B
- ARGF e$B$de(B tty e$B$Je(B IO
e$B$J$I$N7P83$+$i=*N;$OJ#?t2s8!=P$G$-$?$[$&e(B
e$B$,NI$$e(B - peek e$B$GH/@8$7$?e(B StopIteration e$B$G:G=i$KLa$i$l$k$H:$$ke(B
- IO e$B$r85$K:n$C$?e(B Enumerator e$B$G$O$b$H$b$H$=$&$J$ke(B
- 1.8 e$B$Ne(B Generator e$B$G$O$=$&$J$ke(B
- e$BK\Ev$K7+$jJV$7$N:G=i$KLa$j$?$$$J$ie(B rewind e$B$,$"$j!"$=$l$Oe(B
IO e$B$G$be(B (seek e$B$G$-$l$Pe(B) e$BF0$/e(B
% svn diff --diff-cmd diff -x ‘-u -p’
Index: enumerator.c
— enumerator.c (revision 24304)
+++ enumerator.c (working copy)
@@ -32,6 +32,7 @@ struct enumerator {
VALUE args;
VALUE fib;
VALUE dst;
- VALUE lookahead;
VALUE no_next;
};
@@ -59,6 +60,7 @@ enumerator_mark(void *p)
rb_gc_mark(ptr->args);
rb_gc_mark(ptr->fib);
rb_gc_mark(ptr->dst);
- rb_gc_mark(ptr->lookahead);
}
static struct enumerator *
@@ -281,6 +283,7 @@ enumerator_init(VALUE enum_obj, VALUE ob
if (argc) ptr->args = rb_ary_new4(argc, argv);
ptr->fib = 0;
ptr->dst = Qnil;
-
ptr->lookahead = Qundef;
ptr->no_next = Qfalse;return enum_obj;
@@ -361,6 +364,7 @@ enumerator_init_copy(VALUE obj, VALUE or
ptr1->meth = ptr0->meth;
ptr1->args = ptr0->args;
ptr1->fib = 0; -
ptr1->lookahead = Qundef;
return obj;
}
@@ -519,6 +523,7 @@ next_init(VALUE obj, struct enumerator *
VALUE curr = rb_fiber_current();
e->dst = curr;
e->fib = rb_fiber_new(next_i, obj); -
e->lookahead = Qundef;
}
/*
@@ -526,8 +531,8 @@ next_init(VALUE obj, struct enumerator *
- e.next => object
- Returns the next object in the enumerator, and move the internal
-
- position forward. When the position reached at the end, internal
-
- position is rewound then StopIteration is raised.
-
- position forward. When the position reached at the end,
StopIteration
- position forward. When the position reached at the end,
-
- is raised.
- Note that enumeration sequence by next method does not affect other
- non-external enumeration methods, unless underlying iteration
@@ -540,6 +545,16 @@ enumerator_next(VALUE obj)
{
struct enumerator *e = enumerator_ptr(obj);
VALUE curr, v;
-
if (e->lookahead != Qundef) {
-
v = e->lookahead;
-
e->lookahead = Qundef;
-
return v;
-
}
-
if (e->no_next)
-
rb_raise(rb_eStopIteration, “iteration reached at end”);
-
curr = rb_fiber_current();
if (!e->fib || !rb_fiber_alive_p(e->fib)) {
@@ -550,7 +565,7 @@ enumerator_next(VALUE obj)
if (e->no_next) {
e->fib = 0;
e->dst = Qnil;
- e->no_next = Qfalse;
- e->lookahead = Qundef;
rb_raise(rb_eStopIteration, “iteration reached at end”);
}
return v;
@@ -558,6 +573,32 @@ enumerator_next(VALUE obj)
/*
- call-seq:
-
- e.peek => object
-
-
- Returns the next object in the enumerator, but don’t move the
internal
- Returns the next object in the enumerator, but don’t move the
-
- position forward. When the position reached at the end,
StopIteration
- position forward. When the position reached at the end,
-
- is raised.
-
- */
+static VALUE
+enumerator_peek(VALUE obj)
+{
- struct enumerator *e = enumerator_ptr(obj);
- VALUE v;
- if (e->lookahead != Qundef) {
-
v = e->lookahead;
-
return v;
- }
- v = enumerator_next(obj);
- e->lookahead = v;
- return v;
+}
+/*
-
-
call-seq:
-
e.rewind => e
-
Rewinds the enumeration sequence by the next method.
@@ -575,6 +616,7 @@ enumerator_rewind(VALUE obj)e->fib = 0;
e->dst = Qnil;
-
- e->lookahead = Qundef;
e->no_next = Qfalse;
return obj;
}
@@ -868,6 +910,7 @@ Init_Enumerator(void)
rb_define_method(rb_cEnumerator, “with_index”,
enumerator_with_index, -1);
rb_define_method(rb_cEnumerator, “with_object”,
enumerator_with_object, 1);
rb_define_method(rb_cEnumerator, “next”, enumerator_next, 0); - rb_define_method(rb_cEnumerator, “peek”, enumerator_peek, 0);
rb_define_method(rb_cEnumerator, “rewind”, enumerator_rewind, 0);
rb_define_method(rb_cEnumerator, “inspect”, enumerator_inspect, 0);
Index: test/ruby/test_enumerator.rb
— test/ruby/test_enumerator.rb (revision 24304)
+++ test/ruby/test_enumerator.rb (working copy)
@@ -130,5 +130,27 @@ class TestEnumerator < Test::Unit::TestC
assert_equal(3, e.next)
assert_raise(StopIteration) { e.next }
end
+
- def test_peek
- a = [1]
- e = a.each
- assert_equal(1, e.peek)
- assert_equal(1, e.peek)
- assert_equal(1, e.next)
- assert_raise(StopIteration) { e.peek }
- assert_raise(StopIteration) { e.peek }
- end
- def test_next_after_stopiteration
- a = [1]
- e = a.each
- assert_equal(1, e.next)
- assert_raise(StopIteration) { e.next }
- assert_raise(StopIteration) { e.next }
- e.rewind
- assert_equal(1, e.next)
- assert_raise(StopIteration) { e.next }
- assert_raise(StopIteration) { e.next }
- end
end