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 multi-valued object, distinct from an array. m_v objects have special rules for parameter passing and assignment-based variable bindings.
m_v(1, 2, 3) # multi-valued object with 1, 2, 3
No nesting rule: m_v objects automatically un-nest.
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 multi-valued object. If in the middle of another multi-value, 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. multi-values 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 mutli-value 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 multi-valued object. A "," on lhs or param-list might construct something like a multi-valued-binder (something that will bind multiple variables). Unless *splatted, element [i] of a multi-valued binder is always bound to element[i] of the multi-valued object. If splatted, element[i] of a multi-valued binder is bound to an array with elements[i] to elements[length-1] of the multi-valued object.
"," at end of m_v or m_v binder is either a No-Op, 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, 2003-2005.
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...