Hi liszt,
I read on Matz’ Ruby2.0 slides that the semantics
of Multiple Values will change. Are these already
decided? Here are my ideas about the subject.
I want to post it as a RCR, but I would like to have
your opinion, or criticism first. Also I am not
very familiar with the RCR mechanism.
It is already gotten to a quite large and complicated document.
Thanks,
Kristof
TITLE
Semantics of Multiple Values
ABSTRACT
This RCR describes a possible change in semantics of multiple
values, by making them equivalent to argument passing.
PROBLEM
Currently Array’s are used as multiple variables, which
creates some ambiguous or unclear situations.
i.e.: a, b, c = x #where x = [1, 2, 3]
PROPOSAL
- model
···
=======
This proposal favors the use of multiple values as inherent
to the language, rather than a seperate data-type. It is
based on the observation that returning (multiple) values
is similar to passing arguments. This fact is even more clear
when using continuations.
for example:
x, y, z = mymethod(a, b, c)
def mymethod
return r1, r2, r3
end
would mean this
def mymethod
callcc { |cc| cc.call(2, 3, 4) }
end
#(the following isn’t legal syntax, but just to show the meaning)
mymethod(a, b, c) |x, y, z|
basicly the expression:
x, y, z =
will pass the multiple arguments to the given variables like
in function argument passing
The difference with argument passing in functions are the following:
- no new scope is created, bound variable are just replaced
- there is no strict checking if the number of arguments is
correct
- new construct and method
==========================
- new construct:
because Array’s are now treated different from multiple arguments
I would like to suggest the following construct
*[a, b] = [1, 2]
meaning the same as
a, b = *[1, 2]
but usefull inside blocks that pass arrays
- new method:
(for now called values)
method returning multiple values as an array
def values(*params)
params
end
values(1, 2, 4) => [1, 2, 4]
- variable assigment examples:
==============================
def multi
return 1, 2, 3
end
#multi may be replaced everywhere with (1, 2, 3)
- variable asignment
x = multi
=> x == 1
x, y = multi
=> x == 1, y == 2
x, y = multi, 3
=> x == 1, y == 3
(x, y), z = multi, 4
=> x == 1, y == 2, z == 4
(*[x, y], z), p = ([1, 2, 3], 4, 5), 6
=> x == 1, y == 2, z == 4, p == 6
- calling to functions
======================
I would recommend the following behavior:
-
when passing multiple values from one function to another,
spread the values in a relaxed way (don’t check the number
of parameters). When used with an explicit list, use
strict checking.def func1(a) a end
func1(multi)
=> 1func1(1, 2, 3)
=> errordef func2(*a) a end
func2(multi)
=> [1, 2, 3] -
when passing nested multiple variables just pass the first
elementdef func3(a, b) [a, b] end
func3(multi, 4)
=> [1, 4]func3((1, 2), 4)
=> [1, 4]
#or maybe signal error? not sure about this onefunc2(multi, 4)
=> [1, 4]func2(*values(multi), 4)
=> [1, 2, 3, 4] -
allow nested multiple values in method definitions
def func4(a, (b, c), d)
[a, b, c, d]
endfunc4(1, 2, 3)
=> [1, 2, nil, 3]
#maybe raise an error?func4(1, (2, 3), 4)
=> [1, 2, 3, 4]func4(1, multi, 4)
=> [1, 1, 2, 4]def func5(a, *[b, c], d)
func5(1, 2, 3)
=> [1, 2, nil, 3]func5(1, [2, 3], 4)
=> [1, 2, 3, 4]func5(1, (2, 3), 4)
=> [1, 2, nil, 4](what will happen here is only the 2 from (2, 3) will be passed
to func5, converted into an Array, and passed to b
-
Making argument passing and multiple assignment more similar
==============================================================
There may be other features that could be passed from arguments
passing to multiple assignment, for example hash paramaters?
Other may not be appropriate (i.e. blocks).