Feature #15381
openLet double splat call `to_h` implicitly
Description
The single splat calls to_a
implicitly on the object (if it is not an array already) so that, for example, we have the convenience of writing conditions in an array literal:
a = [
*(:foo if some_condition),
*(:bar if another_condition),
]
And the ampersand implicitly calls to_proc
on the object (if it is not a proc already) so that we can substitute a block with an ampersand followed by a symbol:
some_method(&:some_method_name)
Unlike the single splat and ampersand, the double splat does not seem to implicitly call a corresponding method. I propose that the double splat should call to_h
implicitly on the object if it not already a Hash so that we can, for example, write a condition in a hash literal as follows:
h = {
**({a: 1} if some_condition),
**({b: 2) if another_condition),
}
There may be some other benefits of this feature that I have not noticed yet.
Updated by sawa (Tsuyoshi Sawada) over 5 years ago
Sorry, I meant to_h
, not to_hash
.
And in case my intention was not clear, in the example I gave for the double splat, I expected **nil
to be evaluated as **{}
due to nil.to_h # => {}
.
Updated by shevegen (Robert A. Heiler) over 5 years ago
I myself have used *foobar quite a lot in ruby code, such as in:
def foobar(*args)
args.each # and do something then
end
and I have also used &: considerably often too. The most frequent
use case for me personally is to use &: together with .map(). This
is an area where I actually prefer e. g. .map(&:strip) as opposed
to something like .map {|line| line.strip } or something like
that. While I consider the second variant more readable to me,
the &: variant is significantly shorter. (& is not very pretty
though so I try to not use it too often).
I have not yet used **, I think (strangely enough; perhaps I have not
needed it so far). So I can not say much about the proposal itself
either way. I am both clueless and neither pro nor con. :)
I agree with the above reasoning of nil.to_h which makes sense (if
the functionality in itself is approved and I guess we have to ask
matz about this).
I think this is where matz has to decide whether ** should behave as
described, stay as it is (status quo), or have some other (implicit?)
meaning that was not yet mentioned. I really can not say either way,
but I think what is also said in the issue here is that * has a better
defined meaning right now than does **. So this is where I think matz
has to decide either way.
I would recommend adding this suggestion to an upcoming developer meeting,
but perhaps not for 2018 but 2019 instead - last dev meeting this year
should ideally be for the ruby x-mas release. :D
On a side note, does anyone have one or more good or simple use cases
for **? I am trying to find an example for where it may be used but
I do not have any local example.
Last but not least, although I understand that the example given was
mostly to illustrate a point, so that's fine; the * and ** variants
with () and conditionals, are a bit ugly. :P
I understand it is the illustration of an example but I really hope
people don't write code such as "**({a: 1} if some_condition)"; it
takes my brain quite some time to process.
Updated by ted (Ted Johansson) almost 5 years ago
I came here to file this feature request, only to find this had already been proposed. This would be beautiful, indeed. :-)
Updated by Eregon (Benoit Daloze) almost 5 years ago
nil
does not respond to to_hash
though, how do you propose to deal with that?
Should **
call to_h
rather than to_hash
, similar to *
calling to_a
and not to_ary
?
Your comment https://bugs.ruby-lang.org/issues/15381#note-1 shows that, but I read the mailing list and that doesn't include the edit.
Updated by Eregon (Benoit Daloze) almost 5 years ago
- Subject changed from Let double splat call `to_hash` implicitly to Let double splat call `to_h` implicitly
- Description updated (diff)