Hello,

On Do, 2007-September-06 10:17:11, Brian Candler wrote:
> Quick question - what are the current thoughts about named argument passing
> in future versions of Ruby? 
>
> [...]
> Taking this one step further, has it been considered that splat might be
> applied to a hash in the same way? e.g.
>
>    def func(a, b, c)
>      [a, b, c]
>    end
>
>    func( *{:c=>3, :b=>2, :a=>1} )  # => [1,2,3]   :-)

Wow, I really like this idea a lot.

I think this could be taken even a bit further,
by allowing the splat outside method headers:

  h = {:c=>3, :b=>2, :a=>1}
  a, b, c = *h   
  p [a, b, c]  # => [1,2,3]

The most important reason why I like this, 
is because it would give us not only named 
arguments, but named return values too, 
leading to a nice symmetry:

def get_data
  ...
  {:name => name, :zip => zip}
  # the old way would be: [name, zip]
end

# and then we would simply write:
name, zip = get_data 

# or just as well:
zip, name = get_data   # same effect, more robust

Yes, hashes are already used to return multiple values today,  
but I think the clumsy notation (
  d = get_data
  name = d[:name]
  zip = d[:zip]
) prevents many programmers from adopting this practice.


To sum up: 
Yes. I would really like to see something like this in Ruby 3.0




> P.S. By symmetry, I'd suggest that any 'unused' elements could be available
> as a hash too:
>
>   def func(a, b, c=3, *d)
>     p a, b, c, d
>   end
>
>   func( *{:a=>1, :b=>2, :e=>5, :f=>6} )
>   # 1
>   # 2
>   # 3
>   # {:e=>5, :f=>6}
>
> However this does mean that the receiver of *d would have to be able to
> cope with receiving either an Array or a Hash.

OK, I would call that the problem of "reverse splatting".

I.e.: If we allow splat for both arrays and hashes, 
we will be able to determine the type of the splat from the object
if the operator is on the right-hand side.

But we won't have any information, if it is on the left-hand side:
  *x = a, b, c
This could be interpreted as both 
  x = [a, b, c]  
or   
  x =  {:a=>a, :b=>b, :c=>c}

A simple way to deal with that, would be to declare the old interpretation 
(array) as the only one for a LHS-splat.

And the semantics of Brian's example could be preserved in this approach,
because it not only has a LHS-splat, but also a RHS-splat with it.

Essentially it boils down to:
  *d = *{:e=>5, :f=>6}

And we just have to assume an internal "splat reduction", giving:
  d = {:e=>5, :f=>6}



However, it might be nice to have a way to force reverse hash splatting,
for example by a new prefix operator **
  **h = a, b, c
  # =>      h =  {:a=>a, :b=>b, :c=>c}

... but also inviting cans of trouble, like 
  **h = a, b, 42             # result??         
  # perhaps
  # =>      h =  {:a=>a, b=>b, 2=>42}     (position used as key)  



Yes, at this point I really wish that there be a unified Hash-Array 
data structure, as they have in Oz or Lua.



Bye for now


Regards
Sven