From: Yusuke Endoh Date: 2012-02-13T23:27:02+09:00 Subject: [ruby-core:42544] [ruby-trunk - Feature #1125] [*x] (array consisting only of a splat) does not necessarily return a new array Issue #1125 has been updated by Yusuke Endoh. Assignee changed from Yukihiro Matsumoto to Yusuke Endoh Hello, I'll commit the following patch unless there is objection: diff --git a/compile.c b/compile.c index 32bda52..9ea2a3c 100644 --- a/compile.c +++ b/compile.c @@ -4644,6 +4644,8 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE * node, int poped) case NODE_SPLAT:{ COMPILE(ret, "splat", node->nd_head); ADD_INSN1(ret, nd_line(node), splatarray, Qfalse); + ADD_INSN1(ret, nd_line(node), newarray, INT2FIX(0)); + ADD_INSN(ret, nd_line(node), concatarray); if (poped) { ADD_INSN(ret, nd_line(node), pop); -- Yusuke Endoh ---------------------------------------- Feature #1125: [*x] (array consisting only of a splat) does not necessarily return a new array https://bugs.ruby-lang.org/issues/1125 Author: Daniel Luz Status: Assigned Priority: Normal Assignee: Yusuke Endoh Category: Target version: 2.0.0 ruby -v: ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux] =begin For [*x], these are basically the possible outcomes: 1. if x is an Array, returns it unmodified. 2. elsif x responds to to_ary (to_a on 1.9.1), invokes that method and returns its result unmodified. 3. else, returns a new array with x as its only element. Cases #1 and #2 IMO violate the POLS, as I expected that an array literal would always return a new array. The practical consequence here is that I expected I'd be free to modify it without side effects. (For comparison, "#{x}" always returns a new string) Simple test case: x = [1, 2, 3] [*x] << 4 p x # => [1, 2, 3, 4] Thus, I propose ensuring these two cases always return new arrays. One possible solution would be dup'ing the resulting array (I guess that'd have a rather low cost; the third case would result in an unnecessary dup, but at least it's just a single-item array). Another one would be to dumb down the interpreter, making it create a zero-length array and then concat the result of the splat to it. =end -- http://bugs.ruby-lang.org/