From: "H.Yamamoto" Date: 2005-08-30T09:03:48+09:00 Subject: [ruby-dev:26910] Re: multiplying empty string 山本です。 >|以前、[ruby-dev:19980] で話が出た時には、"" * -1 などがエラーでなくな >|るのを気にする人がいたようです。 思いつきですが、s * -2 は s.reverse * 2 とするのはどうでしょうか。 # 数学的にも、負の掛け算は数直線上で反転を意味するのでしっくり来ます。 Index: array.c =================================================================== RCS file: /src/ruby/array.c,v retrieving revision 1.175 diff -u -w -b -p -r1.175 array.c --- array.c 10 Aug 2005 01:39:24 -0000 1.175 +++ array.c 29 Aug 2005 23:59:38 -0000 @@ -2399,6 +2399,7 @@ rb_ary_times(ary, times) { VALUE ary2, tmp; long i, len; + int negative; tmp = rb_check_string_type(times); if (!NIL_P(tmp)) { @@ -2406,10 +2407,9 @@ rb_ary_times(ary, times) } len = NUM2LONG(times); - if (len == 0) return ary_new(rb_obj_class(ary), 0); - if (len < 0) { - rb_raise(rb_eArgError, "negative argument"); - } + if (negative = (len < 0)) len = -len; + + if (len == 0 || RARRAY(ary)->len == 0) return ary_new(rb_obj_class(ary), 0); if (LONG_MAX/len < RARRAY(ary)->len) { rb_raise(rb_eArgError, "argument too big"); } @@ -2421,6 +2421,7 @@ rb_ary_times(ary, times) for (i=0; ilen) { MEMCPY(RARRAY(ary2)->ptr+i, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len); } + if (negative) rb_ary_reverse_bang(ary2); OBJ_INFECT(ary2, ary); return ary2; Index: string.c =================================================================== RCS file: /src/ruby/string.c,v retrieving revision 1.231 diff -u -w -b -p -r1.231 string.c --- string.c 23 Jul 2005 01:02:10 -0000 1.231 +++ string.c 29 Aug 2005 23:59:47 -0000 @@ -400,6 +400,8 @@ rb_str_plus(str1, str2) * "Ho! " * 3 #=> "Ho! Ho! Ho! " */ +static VALUE rb_str_reverse_bang(VALUE); + VALUE rb_str_times(str, times) VALUE str; @@ -407,12 +409,12 @@ rb_str_times(str, times) { VALUE str2; long i, len; + int negative; len = NUM2LONG(times); - if (len == 0) return rb_str_new5(str,0,0); - if (len < 0) { - rb_raise(rb_eArgError, "negative argument"); - } + if (negative = (len < 0)) len = -len; + + if (len == 0 || RSTRING(str)->len == 0) return rb_str_new5(str,0,0); if (LONG_MAX/len < RSTRING(str)->len) { rb_raise(rb_eArgError, "argument too big"); } @@ -424,6 +426,8 @@ rb_str_times(str, times) } RSTRING(str2)->ptr[RSTRING(str2)->len] = '\0'; + if (negative) rb_str_reverse_bang(str2); + OBJ_INFECT(str2, str); return str2;