Let `nil.to_a` and `nil.to_h` return a fixed instance
nil.to_s returns a fixed instance:
nil.to_s.object_id # => 440 nil.to_s.object_id # => 440 nil.to_s.object_id # => 440 ...
This is useful when we have some variable
foo which may be either
nil or a string, and we want to check its emptiness in a condition:
if foo.to_s.empty?; ... end
By this feature, we do not (need to) create a new instance of an empty string each time we check
foo, even when it happens to be
There are similar situations with arrays and hashes. We may have variable
bar which may be either
nil or an array, or
baz which may be either
nil or a hash, and we want to check their emptiness in conditions as follows:
if bar.to_a.empty?; ... end
if baz.to_h.empty?; ... end
nil.to_s, the methods
nil.to_h create new instances of empty array or hash each time they are called:
nil.to_a.object_id # => 540 nil.to_a.object_id # => 560 nil.to_a.object_id # => 580 ... nil.to_h.object_id # => 460 nil.to_h.object_id # => 480 nil.to_h.object_id # => 500 ...
The fact that this is somewhat inefficient discourages the use of
foo.to_h in such use cases.
nil.to_h to return a fixed empty instance.
Updated by shevegen (Robert A. Heiler) 9 months ago
I somewhat agree with the explanation, so I think the suggestion in itself is fine
I believe there may be a language design consideration, though, e. g. whether matz
thinks that this makes sense from a language-design point of view (see the other
explanation about the various attr* methods and why there is no attr* variant
that e. g. combines reader methods with a trailing '?' character).
Another smaller issue, if it is an issue, may be for ruby newcomers. For example,
say that a new user comes to ruby and asks about nil.to_a and nil.to_h
specifically - will there be an explanation somewhere? I am really just thinking
about the new-ruby-user situation in this regard, e. g. they may like to
understand why .to_a and .to_h may be special but not other .to* (if there
are any ... I don't even know how many exist for nil).
Note that these two points are not meaning that I am against the suggestion
at all - it is only meant to "carve out more details" from the proposal if
In my own code I usually check first for nil, before doing any further
checks, even "boolean checks" (if a variable is true or false). Not sure
if that is the best practice, different people write code differently,
but I sort of adopted that a long time ago. So I may not be the ideal
target audience either as I currently don't quite seem to do much on
nil, except actually I do indeed sometimes do .to_s, to ensure that
I have a string. This can indeed be a bit complicated sometimes, if
we have to distinguish between nil, string and a symbol. But I still
agree with your basic statement - it somewhat makes sense to me since
nil.to_a and nil.to_h will always "reproduce" the same result just
as .to_s would (and should, since it is nil).
Updated by byroot (Jean Boussier) 9 months ago
I'm not sure if
nil.to_h are actually frequent sources of allocations, but I agree with the general premise.
When profiling Ruby applications, it's frequent to see 30% of the time being spent in GC, which makes me think reducing useless allocations could lead to increased performance.
However as we've seen with trying to freeze the return of
Symbol#to_s [#16150] , there are some backward compatibility concerns.
So maybe the priority would be to implement [#16153] so that this kind of changes can go through a normal deprecation cycle.