enduro
9/10/2007 10:34:00 AM
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