[ruby-core:109723] [Ruby master Feature#18959] Handle gracefully nil kwargs eg. **nil
From:
"LevLukomskyi (Lev Lukomskyi)" <noreply@...>
Date:
2022-08-26 23:36:27 UTC
List:
ruby-core #109723
Issue #18959 has been updated by LevLukomskyi (Lev Lukomskyi).
> because it’s (1) wasteful
It wastes what? I don't understand this argument
> (2) noisy
This I can understand because indeed sometimes programmers can put too much in one line. However there are only two operators in that line – `if` and `**`, that's not that many, with IDE highlighting it reads easily.
> (3) *impossible* to write good tests for in application code.
This argument I also don't understand – what makes that piece of code *impossible* to write good tests? Eg.:
```ruby
class Example
def build_hash(id = nil, name = nil)
{
some: 'value',
**({ id: id, name: name } if id.present?),
}
end
end
Rspec.describe Example do
describe '#build_hash' do
it 'returns simple hash if id is not set' do
expect(described_class.build_hash).to eq(some: 'value')
end
it 'returns extended hash if id is set' do
expect(described_class.build_hash(123, 'Lev')).to eq(some: 'value', id: 123, name: 'Lev')
end
end
end
```
I've just written simplified tests for application code, no problem.
> Both @sawa and I have provided better options than your examples.
It looks like you guys are ashamed of `**` and try to avoid it at all costs, instead of grasping this new language feature.
I see that I'm not alone and there are other similar issues:
https://bugs.ruby-lang.org/issues/9291
https://bugs.ruby-lang.org/issues/8507
https://bugs.ruby-lang.org/issues/15381
and people @rits, @stephencelis, @kainosnoema, @ted, @Dan0042, @ioquatix like this feature. I guess, there are more people frustrated by `**nil` behavior but they don't have time to write a feature request.
Also, I've found one more [good example](https://www.semicolonandsons.com/code_diary/ruby/double-splat-cannot-handle-nil). Here a programmer has to write this:
```ruby
def add_email_to_list(email:, tracking_info:)
EmailSubscriber.find_by(email: email) || EmailSubscriber.new(
email: email, **(tracking_info || {})
)
...
end
```
instead of just writing this:
```ruby
def add_email_to_list(email:, tracking_info:)
EmailSubscriber.find_by(email: email) || EmailSubscriber.new(
email: email, **tracking_info
)
...
end
```
----------------------------------------
Feature #18959: Handle gracefully nil kwargs eg. **nil
https://bugs.ruby-lang.org/issues/18959#change-98958
* Author: LevLukomskyi (Lev Lukomskyi)
* Status: Open
* Priority: Normal
----------------------------------------
The issue:
```ruby
def qwe(a: 1) end
qwe(**nil) #=> fails with `no implicit conversion of nil into Hash (TypeError)` error
{ a:1, **nil } #=> fails with `no implicit conversion of nil into Hash (TypeError)` error
```
Reasoning:
I found myself that I often want to insert a key/value to hash if a certain condition is met, and it's very convenient to do this inside hash syntax, eg.:
```ruby
{
some: 'value',
**({ id: id } if id.present?),
}
```
Such syntax is much more readable than:
```ruby
h = { some: 'value' }
h[:id] = id if id.present?
h
```
Yes, it's possible to write like this:
```ruby
{
some: 'value',
**(id.present? ? { id: id } : {}),
}
```
but it adds unnecessary boilerplate noise.
I enjoy writing something like this in ruby on rails:
```ruby
content_tag :div, class: [*('is-hero' if hero), *('is-search-page' if search_page)].presence
```
If no conditions are met then the array is empty, then converted to nil by `presence`, and `class` attribute is not rendered if it's nil. It's short and so convenient! There should be a similar way for hashes!
I found this issue here: https://bugs.ruby-lang.org/issues/8507 where "consistency" thing is discussed. While consistency is the right thing to do, I think the main point here is to have fun with programming, and being able to write stuff in a concise and readable way.
Please, add this small feature to the language, that'd be so wonderful! 🙏
--
https://bugs.ruby-lang.org/
Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>