From: "LevLukomskyi (Lev Lukomskyi)" Date: 2022-08-27T22:13:18+00:00 Subject: [ruby-core:109743] [Ruby master Feature#18959] Handle gracefully nil kwargs eg. **nil Issue #18959 has been updated by LevLukomskyi (Lev Lukomskyi). > I also tend to do `**(options || {})` and I don���t write hard-to-read code like `**({id: id, name: name} if id.present?)`. That's interesting, that you are ok for ```ruby **(options || {}) ``` but not ok for ```ruby **(options if condition) ``` which is kind of the same.. > I���d write that as: > > ```ruby > def add_email_to_list(email:, tracking_info: {}) > EmailSubscriber.find_by(email: email) || EmailSubscriber.new(email: email, **tracking_info) > end > ``` This does not solve the issue, the method still can be called with `nil` eg.: ```ruby add_email_to_list(email: 'email@example.com', tracking_info: nil) ``` and it'll raise the error, so you still need that boilerplate code `**(tracking_info || {})` > the example you���ve given is completely unconvincing because it is suboptimal, has unnecessary allocations, and is more reminiscent of what I���d see from Perl in 1998 than Ruby of 2022. that's true, it has an additional allocation if condition is satisfied, although it's not critical in most cases. Also, it could be probably optimized by interpreter in the future, similar to how `[3, 5].max` is optimized. > 1. If we want to allow `**nil`, the argument should be made to switch `**` from calling `#to_hash` to calling `#to_h`, because that would give you `**nil` _for free_. That would require digging a bit deeper to determine why `**` calls `#to_hash` instead of `#to_h`. Agree, `to_hash` method is weird, and it just adds confusion to people about why there are both `to_hash` and `to_h`, and which one they should use. I think `to_hash` should be deprecated and later removed. BTW the issue with `**nil` can be also fixed by this code: ```ruby class NilClass; alias to_hash to_h end ``` > 2. `Hash#merge` and `Hash#update` could be modified to ignore `nil` arguments (which would permit your use-case). Agree, doing nothing on `.merge(nil)` would be good. It will remove redundant allocations like ```ruby hash.merge(other_hash_param || {}) ``` Although I guess it's a more radical change.. One note though, your example: ```ruby { some: 'value' }.merge({ id: id, name: name } if id.present?) ``` won't work as you expect, it raises _SyntaxError: unexpected ')', expecting end-of-input_ The valid way would be: ```ruby { some: 'value' }.update(({ id: id, name: name } if id.present?)) ``` which looks not so nice.. ---------------------------------------- Feature #18959: Handle gracefully nil kwargs eg. **nil https://bugs.ruby-lang.org/issues/18959#change-98979 * 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: