ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
From: "zverok (Victor Shepelev) via ruby-core" <ruby-core@ml.ruby-lang.org>
To: ruby-core@ml.ruby-lang.org
Cc: "zverok (Victor Shepelev)" <noreply@ruby-lang.org>
Subject: [ruby-core:119589] [Ruby master Feature#15381] Let double splat call `to_h` implicitly
Date: Tue, 22 Oct 2024 18:37:08 +0000 (UTC)	[thread overview]
Message-ID: <redmine.journal-110210.20241022183708.2963@ruby-lang.org> (raw)
In-Reply-To: <redmine.issue-15381.20181205082504.2963@ruby-lang.org>

Issue #15381 has been updated by zverok (Victor Shepelev).


> `{}.merge(**obj)` => obj is explicitly splatted but conversion is done via #to_hash instead of #to_h. It makes no sense, as many many people have commented through the years.

I don’t think it can be treated as “explicitly” (invoking hash conversion); it is rather “we apply an operator, which would work with kind-of hash”. We can apply the same argument to `1 + obj`: “you see, I am _explicitly_ summing it with an integer; why is it not converted with `to_int`?”

> `**obj` is my intent, not a typo. 

What if it _is_ a typo/error? Assume this API (frequent in many long-living codebases, which are partially old-style “options hash” and partially new-style “keyword arguments”):

```ruby
def process(something, options = {})
  # ...
  other_method(**options)
end
```
Now, if the user misuses it (by mistake or misunderstanding) and passes some, say, ActiveRecord model as a second parameter, then, with `to_h`, it would be successfully unpacked, and might go this way (as “keyword arguments” which shouldn’t have been) through several more delegating methods before failing in completely different place—with an extremely hard to debug problem.

So, what we are weighting here are:
* convenience of unpacking non-hashes into keyword arguments (BTW, what exactly is the use case for this convenience?..), vs.
* problem of things being _unintentionally_ unpacked, considering how many objects have `to_h` method; basically failing to “fail early” (where the mistake was made) and instead passing the mistake for who-know-which depth.

I honestly fail to see the use case for `to_h` being used with `**` that outweighs the possible problems (other than `**(params if condition?)`, which was actually handled).

----------------------------------------
Feature #15381: Let double splat call `to_h` implicitly
https://bugs.ruby-lang.org/issues/15381#change-110210

* Author: sawa (Tsuyoshi Sawada)
* Status: Open
----------------------------------------
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:

```ruby
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:

```ruby
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:

```ruby
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.



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/

  parent reply	other threads:[~2024-10-22 18:37 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <redmine.issue-15381.20181205082504.2963@ruby-lang.org>
2023-01-17 18:11 ` [ruby-core:111859] " sawa (Tsuyoshi Sawada) via ruby-core
2024-10-21 21:30 ` [ruby-core:119581] " sanjioh (Fabio Sangiovanni) via ruby-core
2024-10-22  6:12 ` [ruby-core:119585] " zverok (Victor Shepelev) via ruby-core
2024-10-22 18:10 ` [ruby-core:119588] " Dan0042 (Daniel DeLorme) via ruby-core
2024-10-22 18:37 ` zverok (Victor Shepelev) via ruby-core [this message]
2024-10-22 19:32 ` [ruby-core:119590] " Dan0042 (Daniel DeLorme) via ruby-core
2024-10-22 19:58 ` [ruby-core:119591] " jeremyevans0 (Jeremy Evans) via ruby-core
2024-10-22 20:20 ` [ruby-core:119592] " Dan0042 (Daniel DeLorme) via ruby-core
2024-10-23  7:57 ` [ruby-core:119595] " zverok (Victor Shepelev) via ruby-core
2024-10-24 11:33 ` [ruby-core:119605] " Eregon (Benoit Daloze) via ruby-core

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=redmine.journal-110210.20241022183708.2963@ruby-lang.org \
    --to=ruby-core@ml.ruby-lang.org \
    --cc=noreply@ruby-lang.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).