Issue #17472 has been updated by timcraft (Tim Craft).


hcatlin (Hampton Catlin) wrote in #note-15:
> Would anyone here think the code below was acceptable?

Mixing symbol keys and string keys together like that would no doubt be very confusing, but why would you choose to do that instead of just using symbol keys or string keys? With modern Ruby the use case handled by options hashes is typically better handled by keyword arguments, and sometimes an options/config object might be a more appropriate choice. Keyword argument hashes use symbol keys, and I would expect options/config objects to be implemented using symbol keys.

We now also have Hash#transform_keys, so transforming a hash with string keys from outside data sources to symbol keys is straightforward. That can easily handle use cases like transforming keys in config/database.yml to symbols. JSON has symbolize_names and so on. There doesn't need to be confusion if library authors make a clear decision on whether to use strings or symbols for a specific use case, instead of trying to support both.

> And this is why Rails has HashWithIndifferentAccess and most of us would prefer to use it in our libraries, and just don't' want to have the awkwardness of having to type out that horribly long name every time.

Maybe I'm in the minority, but I would never use HashWithIndifferentAccess in my own libraries, and I try hard not to use it directly in Rails because I've seen it become the source of confusion and subtle bugs!

I think the critical use case for HashWithIndifferentAccess is params; where you want to be using symbol keys because it's cleaner syntax, but the keys are coming from untrusted input. But HashWithIndifferentAccess is just the historical solution that exists for that case. There's no reason there couldn't be an ActiveSupport::Params class which allowed for `params.title` instead of `params[:title]`, making the choice between whether to use string keys or symbol keys disappear (in the calling code at least).

> In almost every use of Hash in my career, the keys have being either symbols or strings, and I can't think of production code that even uses the fact that you can use an object as a key as a feature. I think I've attempted it myself a couple times, but usually refactored the code after, berating myself for trying to be a little too clever.

I have a lot of code which does, plenty of it in production. Hashes that represent a set of attributes, hashes that represent a set of variables (e.g. for template locals), and keyword argument hashes are relatively frequent examples for using symbol keys. The syntax for hash literals with symbol keys is so much nicer to read and write than the hashrocket syntax with string keys.

Apart from symbols the other common use case I encounter is time series data. I frequently use date keys, integer keys for years, month keys, and quarter keys. Having this as an option instead of only being able to use strings is one of the reasons I prefer Ruby to other languages. And I don't consider that kind of code to be clever. Quite the opposite, it feels like "boring" code which just works.

> In the last year I've come back to full time Ruby programming, and this remains one of my biggest frustrations with the language.

Welcome back to Ruby! :) Are you working on Rails apps? If so it seems a little unfair to get frustrated at the language for choices made by the web framework. If not can you share an example of a Ruby use case that would be significantly improved by HashWithIndifferentAccess?

----

FWIW I'm against this proposal for the reasons already mentioned:

* The name is terrible, which apart from making it clumsy to use and not seeming very Ruby-ish I think demonstrates that the semantics of the class are a bit unclear. As Jeremy points out it is not indifferent in many respects, just with symbols and strings.

* There isn't any profiling data which shows this is a significant bottleneck for a significant number of Rails projects. Optimizing performance for Date, Time, BigDecimal, JSON, URI, YAML etc would benefit Rails *and* a broader range of Ruby applications.

* Re-implementing in C adds more work for maintainers of alternative Ruby implementations, for seemingly little benefit.

The original motivation here seems to be for improving performance of Rails applications. Why does it need to be in Ruby core/stdlib? Why can't it just be implemented as a C extension packaged in a gem?


----------------------------------------
Feature #17472: HashWithIndifferentAccess like Hash extension
https://bugs.ruby-lang.org/issues/17472#change-90064

* Author: naruse (Yui NARUSE)
* Status: Open
* Priority: Normal
* Target version: 3.1
----------------------------------------
Rails has [ActiveSupport::HashWithIndifferentAccess](https://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html), which is widely used in Rails to handle Request, Session, ActionView's form construction, ActiveRecord's DB communication, and so on. It receives String or Symbol and normalize them to fetch the value. But it is implemented with Ruby. If we provide C implementation of that, Rails will gain the performance improvement.

summary of previous discussion: https://github.com/rails/rails/pull/40182#issuecomment-687607812



-- 
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>