Submitted by itsme213 (Fri Jan 14 13:01:25 UTC 2005)
multiv = 1, 2, 3 # multiv=expr = [1, 2, 3] def f multiv; multiv; end f 1, 2, 3 #=> ArgumentError
unsplat = *[1, 2, 3] # unsplat=expr = [1, 2, 3] def f unsplat; unsplat; end f *[1, 2, 3] #=> ArgumentError
*splat = 1, 2, 3 # splat=expr = [1, 2, 3] def f *splat; splat; end f 1, 2, 3 #=> splat=expr = [1, 2, 3]
firstvalue, = 1, 2, 3 # firstvalue = 1; expr = [1, 2, 3] def f(firstvalue,); firstvalue; end #=> syntax error
Assume m_v constructs a multivalued object, distinct from an array. m_v objects have special rules for parameter passing and assignmentbased variable bindings.
m_v(1, 2, 3) # multivalued object with 1, 2, 3
No nesting rule: m_v objects automatically unnest.
m_v(1, m_v(2, 3), 4) == m_v(1, 2, 3, 4)
A * on the rhs of assignment, or on an arg value passed in to a call, or on the return value of a method, always does unsplat i.e. converts array following the * to multivalued object. If in the middle of another multivalue, it is inserted flat (see no nesting rule).
*[1, 2, 3] # expr = m_v(1, 2, 3) f(*[1, 2, 3]) # f m_v(1, 2, 3), same as f(1,2,3) f; return *[1, 2, 3]; end # return m_v(1, 2, 3) x = *1 #=> ArgumentError, can only unsplat Array 1, *[2, 3], 4 #=> m_v(1, 2, 3, 4)
A * on the last position on lhs of assignment, or the last positional param list of a method or proc or block, always does a splat i.e. multivalues to array + bind var to that array (or to []}. The expression value (where needed) is the original RVALUE single object or m_v.
x, *y = 1, 2, 3 #=> x=1, y=[2,3], expr=m_v(1, 2, 3) x, *y = 1 # x=1, y=[], expr=1 def f(x,*y); puts x, y; end f(1,2,3) # x=1, y= [2, 3] x, y, z = 1, *[2, 3], 4 # x=1, y=2, z=3, expr = m_v(1, 2, 3, 4) x, y, z = 1, [2,3], 4 # x=1, y=[2,3], z=4, expr = m_v(1, [2,3], 4) def g(x,y,z,u,v,*spl); [x,y,z,u,v,spl]; end def h; return 1, 2; end g(0, h, 3) #=> [0, 1, 2, 3, nil, []]
Without a * on a lhs variable (or the param list of a method), that variable is always bound to the corresponding position in a mutlivalue object (with default bind to nil for assignment, argument error for params). Expression value (where needed) is the original single value or m_v.
x = 1, 2, 3 # x =1; expr = m_v(1, 2, 3) def f x; x; end f 1 #=> 1 f 1, 2 #=> ArgumentError
A "," on a rhs of assignment, or on actual params to a call constructs a multivalued object. A "," on lhs or paramlist might construct something like a multivaluedbinder (something that will bind multiple variables). Unless *splatted, element [i] of a multivalued binder is always bound to element[i] of the multivalued object. If splatted, element[i] of a multivalued binder is bound to an array with elements[i] to elements[length1] of the multivalued object.
"," at end of m_v or m_v binder is either a NoOp, or is not allowed.
In many cases, such m_v object is not directly accessible, and can be optimized by Ruby.
e.g. x = (y, z = 1, 2) # x = m_v (1, 2) # x = 1 # m_v not accessible y, x = 1, 2 # y = 1, x = 2, m_v not accessible
multiv = 1, 2, 3 # multiv=1; expr = m_v(1, 2, 3) def f multiv; multiv; end f 1, 2, 3 #=> ArgumentError
unsplat = *[1, 2, 3] # unsplat=1; expr=m_v(1, 2, 3) def f unsplat; unsplat; end f *[1, 2, 3] #=> ArgumentError
*splat = 1, 2, 3 # splat=[1,2,3]; expr=m_v(1, 2, 3) def f *splat; splat; end f 1, 2, 3 #=> splat=[1,2,3]; expr=[1, 2, 3]
firstvalue,=1,2,3 # firstvalue=1;expr=m_v(1, 2, 3) # or syntax error def f(firstvalue,); firstvalue; end #=> syntax error
Can return multiple values without clients having to be aware of it unless they want to (Just as client does not have to pass in certain parameter values unless they want to).
Con: Not compatible with 1.8.2 behavior.
Comments  Current voting  


RCRchive copyright © David Alan Black, 20032005.
Powered by .
I'd support this. But, I'm sure many would complain of the incompatibilities. Along with this RCR, I'd also say that methods should be able to return this type of thing:
def test;return(1,2,3);end
x,y,z = test # x=1, y=2, z=3
Also, I was thinking that when one of these tuples is in the context of a simple expression, it should return the first element:
test+4 # 1+4 # 5 x = test # x = 1
This could also be used to do post operation:
x, (x+=1) # equivalent to begin; tmp=x;x+=1;tmp; end
Doing it this way, you'd never need to expose these tuples as real objects.
Also, I guess the * operator could generate a tuple using the each method of the object it is splatting. Then you could splat anything instead of just arrays.
But, all of this will create incompatibilities...