Hi, here is my update RCR.
It adds a unify operator := , multiple variables
comparison, and some more goodies (:-)

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 separate data-type. It is based on the
observation that returning (multiple) values is similar to passing
arguments. This is even more apparent when using continuations.

for example:

  def mymethod(a, b)
    return a + 1, b + 2, a
  end

  x, y, z = mymethod(1, 2)

would mean this

  def mymethod(a, b)
    callcc { |cc| cc.call(a + 1, b + 2, a) }
  end

  #(the following isn't legal syntax, but just to show the meaning)
  mymethod(1, 2) |x, y, z|

basicly the expression:

  x, y, z = <expression returning multiple arguments>

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 constructs and method
============================

-  new constructs:
------------------
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 useful inside blocks that pass arrays. Optionally allow:

*[a, *b] = [1, 2, 3]
=> a == 1, b == [2, 3]

or perhaps with hashes:

*{:a => c, :b => d} = {a: 1, b: 2}
=> c == 1; b == 2

*{:a => c, *b} = {a: 1, b: 2, c: 3}
=> c = 1, b = {:b => 2, :c => 3}

these constructs would work both in argument passing and variable
assignment.

-  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)

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)
        => 1
    
        func1(1, 2, 3)
        => error
    
        def func2(*a) a end
    
        func2(multi)
        => [1, 2, 3]
    
        def func3(a, b) [a, b] end
    
        func3(multi)
        => [1, 2]
    
*   when passing nested multiple variables just pass the first element
    
        func3(multi, 4)
        => [1, 4]
    
        func3((1, 2), 4)
        => [1, 4]
        #or maybe signal error?  not sure about this one
    
        func2(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]
        end
    
        func4(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 of multiple assignment that could be taken
from argument passing, for example hash parameters(?). Other may not
be appropriate (i.e. blocks).

example:

def func6
  return 4, b: 5, c:6
end

a, b:, **keys = func6
=> a == 4; b == 5; keys == {:c=>6}

*  Comparing multiple values
============================

Multiple values may be compared using comparison operators. For
example:

a, b, (c, d), e == 1, 2, (3, 4), 5

would mean

a == 1 && b == 2 && c == 3 && d == 4 && e == 5

with the exception that in the first, all the expressions will be
evaluated. It would return false if the number of arguments to the left
aren't equal to the ones to the right.

It would be also useful to be able to compare with the operator ===, so
multiple values can be compared inside case statements. When
comparing one value with multiple values, return true if at least on
matches.

1 === (1, 2, 3)
=> true
#same as 1 === 1 or 1 === 2 or 1 === 3

case a, b
when 1, 2
  puts "is 1 and 2"
when (2, 3), 4
  puts "is (2 or 3) and 4"
end

*  Unify operator
=================

This section descibes a unify operator, that works like a combination
of comparison and assignment (similar to unify in Prolog). The
expression

a, b, c := multi

would assign the lefthand values, if unbound (or nil?) to the
corresponding righthand value, and if bound (or an immediate value)
compare if they are equal. If one of the comparisons would return false,
no assignment will be done.

examples:

a, b, c := 1, 2
=>true  (a == 1, b == 2, c == unbound or nil)

a, b := 1, 3
=>false (a == 1, b == 2, c == unbound or nil)

a, c := 1, 2
=>true (a == 1, b == 2, c == 2)

def amethod
  return true, 1, 2,
end
true, x, y := amethod
=>true (x == 1, y == 2)

ANALYSIS

The changes I proposed here provide a consistent way of using multiple
values, by using (mostly) the same semantic model for assignment as for
argument passing, without losing any power to the language. The major
drawback is that programs written using the old semantics may not work
correctly, (but the current behavior will change anyway?). It also
descibes some other extensions to the language that may or may not be
useful.

IMPLEMENTATION

These changes will have to be made to the core of the language. Some
features I described above may be to hard to implement or decrease
performance (nested multiple values in method definitions,
assigning variables from hash elements), and therefor disallowed.