Hello,
	I've looked that negative ranges are not allowed in Ruby.

	I'd like to discuss, if it is possible permit them...

Example:
	(10..-10).each |i| do puts i end
		does nothing in current Ruby
	(10..-10).step(2)
		does nothing in current Ruby

This patch make the example works (and fixes some funny step's value
like 0 (causes never ending loop) and < 0 (causes overroll).

	I'm waiting for your comments :-)

		Michal

PS: This is initial version for me to see if you will agree with further
development...

Index: range.c
===================================================================
RCS file: /src/ruby/range.c,v
retrieving revision 1.32
diff -u -r1.32 range.c
--- range.c	2002/04/24 04:54:14	1.32
+++ range.c	2002/04/29 20:59:42
@@ -74,11 +74,11 @@
     
     rb_scan_args(argc, argv, "21", &beg, &end, &flags);
     /* Ranges are immutable, so that they should be initialized only once. */
-    if (rb_ivar_defined(obj, id_beg)) {
+    if (RTEST(rb_ivar_defined(obj, id_beg))) {
 	rb_name_error(rb_intern("initialized"), "`initialize' called twice");
     }
     range_init(obj, beg, end, RTEST(flags));
-    return Qnil;
+    return obj;
 }
 
 static VALUE
@@ -231,59 +231,6 @@
 }
 
 static VALUE
-range_each(range)
-    VALUE range;
-{
-    VALUE b, e;
-
-    b = rb_ivar_get(range, id_beg);
-    e = rb_ivar_get(range, id_end);
-
-    if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */
-	long end = FIX2LONG(e);
-	long i;
-
-	if (!EXCL(range)) end += 1;
-	for (i=FIX2LONG(b); i<end; i++) {
-	    rb_yield(INT2NUM(i));
-	}
-    }
-    else if (TYPE(b) == T_STRING) {
-	rb_str_upto(b, e, EXCL(range));
-    }
-    else if (rb_obj_is_kind_of(b, rb_cNumeric)) {
-	b = rb_Integer(b);
-	e = rb_Integer(e);
-
-	if (!EXCL(range)) e = rb_funcall(e, '+', 1, INT2FIX(1));
-	while (RTEST(rb_funcall(b, '<', 1, e))) {
-	    rb_yield(b);
-	    b = rb_funcall(b, '+', 1, INT2FIX(1));
-	}
-    }
-    else {			/* generic each */
-	VALUE v = b;
-
-	if (EXCL(range)) {
-	    while (r_lt(v, e)) {
-		if (r_eq(v, e)) break;
-		rb_yield(v);
-		v = rb_funcall(v, id_succ, 0, 0);
-	    }
-	}
-	else {
-	    while (r_le(v, e)) {
-		rb_yield(v);
-		if (r_eq(v, e)) break;
-		v = rb_funcall(v, id_succ, 0, 0);
-	    }
-	}
-    }
-
-    return range;
-}
-
-static VALUE
 r_step_str(args)
     VALUE *args;
 {
@@ -313,29 +260,51 @@
 
     b = rb_ivar_get(range, id_beg);
     e = rb_ivar_get(range, id_end);
-    rb_scan_args(argc, argv, "01", &step);
+    if (rb_scan_args(argc, argv, "01", &step) == 0) {
+	step = INT2FIX(1);
+    }
 
     if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */
-	long end = FIX2LONG(e);
-	long i, s = (argc == 0) ? 1 : NUM2LONG(step);
-
-	if (!EXCL(range)) end += 1;
-	for (i=FIX2LONG(b); i<end; i+=s) {
-	    rb_yield(INT2NUM(i));
+	long beg = FIX2LONG(b), end = FIX2LONG(e), s = NUM2LONG(step);
+	long i;
+	if (s <= 0) {
+	    rb_raise(rb_eArgError, "step can't be <= 0");
 	}
-    }
-    else if (rb_obj_is_kind_of(b, rb_cNumeric)) {
+	if ((end - beg) < 0) {
+	    if (!EXCL(range)) end -= 1;
+	    for (i=beg; i>end; i-=s) {
+		rb_yield(LONG2NUM(i));
+	    }
+	} else {
+	    if (!EXCL(range)) end += 1;
+	    for (i=beg; i<end; i+=s) {
+		rb_yield(INT2NUM(i));
+	    }
+	}
+    } else if (rb_obj_is_kind_of(b, rb_cNumeric)) {
+	VALUE diff;
 	b = rb_Integer(b);
 	e = rb_Integer(e);
 	step = rb_Integer(step);
 
-	if (!EXCL(range)) e = rb_funcall(e, '+', 1, INT2FIX(1));
-	while (RTEST(rb_funcall(b, '<', 1, e))) {
-	    rb_yield(b);
-	    b = rb_funcall(b, '+', 1, step);
+	if (RTEST(rb_funcall(step, rb_intern("<="), 1, INT2FIX(0)))) {
+	    rb_raise(rb_eArgError, "step can't be <= 0");
 	}
-    }
-    else if (TYPE(b) == T_STRING) {
+	diff = rb_funcall(e, '-', 1, b);
+	if (RTEST(rb_funcall(diff, '<', 1, INT2FIX(0)))) {
+	    if (!EXCL(range)) e = rb_funcall(e, '-', 1, INT2FIX(1));
+	    while (RTEST(rb_funcall(b, '>', 1, e))) {
+		rb_yield(b);
+		b = rb_funcall(b, '-', 1, step);
+	    }
+	} else {
+	    if (!EXCL(range)) e = rb_funcall(e, '+', 1, INT2FIX(1));
+	    while (RTEST(rb_funcall(b, '<', 1, e))) {
+		rb_yield(b);
+		b = rb_funcall(b, '+', 1, step);
+	    }
+	}
+    } else if (TYPE(b) == T_STRING) {
 	VALUE args[5];
 	long iter[2];
 
@@ -343,8 +312,7 @@
 	iter[0] = 1; iter[1] = NUM2LONG(step);
 	rb_iterate((VALUE(*)_((VALUE)))r_step_str, (VALUE)args, r_step_str_i,
 		   (VALUE)iter);
-    }
-    else {			/* generic each */
+    } else {			/* generic each */
 	VALUE v = b;
 	long lim = NUM2INT(step);
 	long i;
@@ -366,8 +334,14 @@
 	    }
 	}
     }
-
     return range;
+}
+
+static VALUE
+range_each(range)
+    VALUE range;
+{
+    return range_step(0, NULL, range);
 }
 
 static VALUE

-- 
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Michal Rokos                         Czech Technical University, Prague
E-mail:m.rokos / sh.cvut.cz  ICQ:36118339  Jabber:majkl / jabber.sh.cvut.cz
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-