Feature #6737
closed
Add Hash#read and alias as #[].
Added by trans (Thomas Sawyer) over 12 years ago.
Updated almost 7 years ago.
Description
Just, generally speaking it is nice to have a word named method for things when that suites readability better. Most operators (outside of numerical math, of course) have word equivalents. I actually hope you will accept this request based on this merit alone.
But more specifically this is also related to #6442, "CRUDifying" Hash's design. Adding #read is essentially the first step in doing this. Since #read, being the "R" in CRUD, would be one of the core methods, its preferable to have word-named method to go along with other methods, #store (for create and update) and #delete to act as that foundation.
Obviously there is nothing earth shattering here, just asking for an alias at this point. I'd like to incrementally submit requests/patches to "CRUDify" Hash rather then submit one huge patch as it will be much easier to test and ensure backward compatibility that way.
Files
What is wrong with #fetch?
What is wrong with #fetch ?
There's one important difference, #fetch
raises an error when a key isn't present, whereas #read returns nil. I worked on the design in pure Ruby, and at first I did try using #fetch, but ultimately concluded it was best to depend on #read and #key?. It's easy enough to write #fetch in terms of the other two, but the other way round involves catching the error that #fetch raises, and that is too inefficient.
- Status changed from Open to Feedback
Based on the note in #6442, it is probably best you submit patches related to that feature request (such as this one for #read) there. There's no need to create separate issues for the patches you are going to submit. If you don't wish to submit one large patch for the four methods you wish to add that is fine.
#fetch takes optional second argument. Tell us how inefficient it is.
@dbrian In part I wanted to submit this on it's own merits as well. I hesitated to even bring up #6442. I personally find having word forms for "symbol" methods a good thing in itself because they have semantic value and read better, which is nice in certain cases. Admittedly its sort of an aesthetics suggestion --where as we have #store as a equivalent for #[]=, I'd like to see #read for #[].
As for a patch for #6442, an all-in-one patch would be quite extensive. It's not about adding four methods, it's about adjusting every other method to utilize them.
@shyouhei (Shyouhei Urabe)
Well, you learn something new every day! Has #fetch always had second default argument?
I think that can work for #6442 then. The inefficiency I was concerned about was just about the error rescue.
Although... I imagine there must be an extra condition in #fetch to decide whether to raise an error or return a default instead. That would be a very minor inefficiency, so maybe we say no big deal. Still, if we wanted to eek out every bit of performance we might consider #read. I am certain #[] is used far more often then #fetch, and often enough that even one less condition might have a noticeable impact?
trans (Thomas Sawyer) wrote:
Has #fetch always had second default argument?
I think so.
Although... I imagine there must be an extra condition in #fetch to decide whether to raise an error or return a default instead.
The behaviour of #[] is, to say in English,
(1) seek for the key
(2) if the hash conains the key, returns that
(3) else if the hash has default value, returns that
(4) else if the hash has default_proc, calls that
(5) otherwise returns nil.
and that of #fetch is,
(1) seek for the key
(2) if the hash conains the key, returns that
(3) else if optional second argument is given, returns that
(4) else if optional block argument is given, calls that
(5) otherwise raises exception.
So overheads are minimal, if any.
=begin
Oh, thanks Shyouhei. That is very helpful breakdown. So I infer then, #[] (aka read) can be defined via #fetch as:
def
fetch(key, default, &default_proc)
end
(And if so, save converting to C, this would be the first CRUDified method definition.)
=end
=begin
I attempted to use #fetch as the CRUD method of reading and ran into an issue that may make it infeasible. Because #fetch accepts an argument or block for the default, it never handles the instance-level default or default_proc. In other words, there is no way to have #fetch return the default that was defined upon initialization, e.g.
h = Hash.new{ |h,k| h[k] = "DEFAULT" }
h.fetch(:x) #=> "DEFAULT"
If there is no way for #fetch to do this, then it is not enough to act as the CRUD method for reading. So we would still need to depend on #[], and as a CRUD method (and the purpose of this ticket), we should have a word form for the method to go along with the other CRUD methods.
Btw, if #read is not considered a good choice, perhaps b/c it is too reminiscent of an IO object, then another name like #retrieve would be okay.
=end
- Target version changed from 2.0.0 to 2.6
This was a simple enough feature so I made a patch (with the assumption that #retrieve is an acceptable name for this method). I hope this will be accepted --the Hashery project really needs to be able to depend on an official name for this method.
- Target version deleted (
2.6)
Also available in: Atom
PDF
Like0
Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0Like0