From: Tadayoshi Funaba Date: 2007-08-22T22:16:26+09:00 Subject: [ruby-dev:31599] Re: [ ruby-Bugs-9490 ] Date module, step method, infinite loop if +step+ is 0 should raise an exception? step メソッドについて、step が零の場合、直ちにエラーにするということで 合せませんか (添付のように)。Range でもそうなのですが、現状では、なん ら検査もなく、Enumerator が生成されるので、引数エラーのすべてが遅延さ れてしまいます。 あるいは、この際、step の零を認めるということでもいいかもしれません。 Inf = 1.0/0 e = 0.step(0,0).zip(0.step(Inf)) e.each{|a| p a} といったことが出来でも悪くはないと思います。 Index: lib/date.rb =================================================================== --- lib/date.rb (revision 13230) +++ lib/date.rb (working copy) @@ -1400,11 +1400,14 @@ # we reach +limit+ (inclusive), yielding the resultant # date at each step. def step(limit, step=1) # :yield: date + if step.zero? + raise ArgumentError, "step can't be 0" + end unless block_given? return to_enum(:step, limit, step) end da = self - op = %w(- <= >=)[step <=> 0] + op = %w(? <= >=)[step <=> 0] while da.__send__(op, limit) yield da da += step Index: range.c =================================================================== --- range.c (revision 13230) +++ range.c (working copy) @@ -287,8 +287,6 @@ VALUE b, e, step; long unit; - RETURN_ENUMERATOR(range, argc, argv); - b = rb_ivar_get(range, id_beg); e = rb_ivar_get(range, id_end); if (rb_scan_args(argc, argv, "01", &step) == 0) { @@ -301,6 +299,9 @@ } if (unit == 0) rb_raise(rb_eArgError, "step can't be 0"); + + RETURN_ENUMERATOR(range, argc, argv); + if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */ long end = FIX2LONG(e); long i; @@ -380,8 +381,6 @@ { VALUE beg, end; - RETURN_ENUMERATOR(range, 0, 0); - beg = rb_ivar_get(range, id_beg); end = rb_ivar_get(range, id_end); @@ -389,6 +388,9 @@ rb_raise(rb_eTypeError, "can't iterate from %s", rb_obj_classname(beg)); } + + RETURN_ENUMERATOR(range, 0, 0); + if (FIXNUM_P(beg) && FIXNUM_P(end)) { /* fixnums are special */ long lim = FIX2LONG(end); long i; Index: numeric.c =================================================================== --- numeric.c (revision 13230) +++ numeric.c (working copy) @@ -1394,7 +1394,6 @@ { VALUE to, step; - RETURN_ENUMERATOR(from, argc, argv); if (argc == 1) { to = argv[0]; step = INT2FIX(1); @@ -1411,6 +1410,7 @@ rb_raise(rb_eArgError, "step can't be 0"); } } + RETURN_ENUMERATOR(from, argc, argv); if (FIXNUM_P(from) && FIXNUM_P(to) && FIXNUM_P(step)) { long i, end, diff;