What advantage does:
foo = [1, 2, *[3, *[4], 5], 6, *[7, 8, 9]]
give over:
foo = [1, 2] + ([3] + [4] + [5]) + [6] + [7, 8, 9]
If * works on the last element, it's surprising to me that it doesn't work on other elements, which of course violates the Principle of Least Surprise that Ruby holds so dearly.
Right now, if you need to expand an array in the middle of a method's argument list, you need to do something like this:
tmp = [1, 2, 3] + some_array + [4, 5, 6]
method(*tmp)
I hope you agree with me that this:
method(1, 2, 3, *some_array, 4, 5, 6)
would be much nicer.
You're probably right about the limited utility of doing this in array literals, but then again there's no reason not to make array literals behave like this as well :-)
No, it only violates the Principle of Never Surprising Anyone, which is very different from POLS :-)
I like your idea, though. I wonder whether there's a parsing issue of some kind.
I've actually taken a look at how this could be implemented (i.e. what changes would be needed in parse.y / eval.c), and what's come out is that Ruby's internals are somewhat crufty. Unfortunately, it seems that one needs to know Japanese to participate in ruby-dev, which puts us English-speakers at a distinct disadvantage (eek, tried the "E"nglish translation button on a ruby-dev message and the translation started "It is cotton.").
Anyway. Currently the restriction of *-expansion to the end of an array is because the node tree is built by inserting a "NODE_ARGSCAT" before ("above") the "NODE_ARRAY" (ref: parse.y calls to arg_concat which creates said node); when eval'd, NODE_ARGSCAT simply evals its params and does an rb_ary_concat. IOW, it's a hack, and Matz is no Larry.
What I see as the solution is to create a two new nodes, NODE_XARRAY (extended array) and NODE_XELEMENT (expand element). When eval'd, XARRAY will eval its children, behaving as ARRAY except for NODE_XELEMENTs, which it will concat rather than push. Thus [1,*a,3] becomes NODE_XARRAY -> (1) -> NODE_XELEMENT (a) -> 3. My reason to keep NODE_ARRAY around is for speed; knowing the number of elements beforehand can be more efficient (take a look at the C code, e.g. in eval.c's SETUP_ARGS macro); however it's probably quite possible to code NODE_ARRAY adaptively and only be slower for *-processing, which would be a superior solution, IMO.
parse.y will also need to be changed, but this actually simplifies things as (on the rhs) *a (tSTAR arg) is no longer a special case restricted to be last.
While we're on the topic, the NODE_ZARRAY seems fairly redundant, in that it should be just a NODE_ARRAY with zero elements (#define NEW_ZARRAY rb_node_newnode(NODE_ARRAY,0,0,0) in node.h), but maybe it's done for speed reasons; I hope so.
So who do I talk to about this? comp.lang.ruby gave me no joy. How about an English fork of Ruby? (HHOS)
czth
Why? (cout, 2002-09-09 12:12:02)
foo = [1, 2, *[3, *[4], 5], 6, *[7, 8, 9]]
give over:
foo = [1, 2] + ([3] + [4] + [5]) + [6] + [7, 8, 9]
Consistency (jcg, 2002-09-09 13:22:38)
Also, method calling (jcg, 2002-09-09 13:57:06)
You're probably right about the limited utility of doing this in array literals, but then again there's no reason not to make array literals behave like this as well :-)
PONSA (dblack, 2002-09-10 07:40:29)
I like your idea, though. I wonder whether there's a parsing issue of some kind.
Implementation (czth, 2002-11-18 14:56:08)
Anyway. Currently the restriction of *-expansion to the end of an array is because the node tree is built by inserting a "NODE_ARGSCAT" before ("above") the "NODE_ARRAY" (ref: parse.y calls to arg_concat which creates said node); when eval'd, NODE_ARGSCAT simply evals its params and does an rb_ary_concat. IOW, it's a hack, and Matz is no Larry.
What I see as the solution is to create a two new nodes, NODE_XARRAY (extended array) and NODE_XELEMENT (expand element). When eval'd, XARRAY will eval its children, behaving as ARRAY except for NODE_XELEMENTs, which it will concat rather than push. Thus [1,*a,3] becomes NODE_XARRAY -> (1) -> NODE_XELEMENT (a) -> 3. My reason to keep NODE_ARRAY around is for speed; knowing the number of elements beforehand can be more efficient (take a look at the C code, e.g. in eval.c's SETUP_ARGS macro); however it's probably quite possible to code NODE_ARRAY adaptively and only be slower for *-processing, which would be a superior solution, IMO.
parse.y will also need to be changed, but this actually simplifies things as (on the rhs) *a (tSTAR arg) is no longer a special case restricted to be last.
While we're on the topic, the NODE_ZARRAY seems fairly redundant, in that it should be just a NODE_ARRAY with zero elements (#define NEW_ZARRAY rb_node_newnode(NODE_ARRAY,0,0,0) in node.h), but maybe it's done for speed reasons; I hope so.
So who do I talk to about this? comp.lang.ruby gave me no joy. How about an English fork of Ruby? (HHOS)
czth