Commit 182096d8 authored by Koichi ITO's avatar Koichi ITO

Make `Array#*` the CRuby compatible behavior when giving a string argument

## Summary

This following is a behavior from CRuby 1.8.7 to 3.1.0.

```console
% ruby -ve "p ['a', 'b', 'c']*''"
ruby 1.8.7 (2013-12-22 patchlevel 375) [i686-darwin13.0.2]
"abc"

% ruby -ve "p ['a', 'b', 'c']*''"
ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x86_64-darwin19]
"abc"
```

### Before (mruby 3.0.0)

mruby unexpectedly gives the TypeError.

```ruby
['a', 'b', 'c']*'' #=> String cannot be converted to Integer (TypeError)
```

### After

This PR makes mruby behave compatible with CRuby.

```ruby
['a', 'b', 'c']*'' #=> 'abc'
```

As far as I checked, the behavior is unspecified when `Array#*`'s argument
is not an instance of Integer class in X 3017 : 2013 (ISO/IEC 30170 : 2012).

## Additional Information

I noticed this difference by the following idiom when writing ASCII art code
using Ruby.

```ruby
%w(foo bar baz)*''
```

e.g. TRICK (https://github.com/tric)
parent 6cc6d9b0
......@@ -425,9 +425,15 @@ mrb_ary_times(mrb_state *mrb, mrb_value self)
{
struct RArray *a1 = mrb_ary_ptr(self);
struct RArray *a2;
mrb_value *ptr;
mrb_value *ptr, sep, tmp;
mrb_int times, len1;
mrb_get_args(mrb, "o", &sep);
tmp = mrb_check_string_type(mrb, sep);
if (!mrb_nil_p(tmp)) {
return mrb_ary_join(mrb, self, tmp);
}
mrb_get_args(mrb, "i", &times);
if (times < 0) {
mrb_raise(mrb, E_ARGUMENT_ERROR, "negative argument");
......
......@@ -32,6 +32,8 @@ assert('Array#*', '15.2.12.5.2') do
end
assert_equal([1, 1, 1], [1].*(3))
assert_equal([], [1].*(0))
assert_equal('abc', ['a', 'b', 'c'].*(''))
assert_equal('0, 0, 1, {:foo=>0}', [0, [0, 1], {foo: 0}].*(', '))
end
assert('Array#<<', '15.2.12.5.3') do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment