Feature #6737

Add Hash#read and alias as #[].

Added by Thomas Sawyer almost 2 years ago. Updated over 1 year ago.

[ruby-core:46492]
Status:Feedback
Priority:Normal
Assignee:-
Category:core
Target version:next minor

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.

hash.patch Magnifier (842 Bytes) Thomas Sawyer, 11/06/2012 06:42 AM


Related issues

Related to ruby-trunk - Feature #6442: CRUDify Hash class Feedback 05/17/2012

History

#1 Updated by Eric Hodel almost 2 years ago

What is wrong with #fetch?

#2 Updated by Thomas Sawyer almost 2 years ago

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.

#3 Updated by Eric Hodel almost 2 years ago

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

#4 Updated by Shyouhei Urabe almost 2 years ago

#fetch takes optional second argument. Tell us how inefficient it is.

#5 Updated by Thomas Sawyer almost 2 years ago

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

#6 Updated by Thomas Sawyer almost 2 years ago

@shyouhei

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?

#7 Updated by Shyouhei Urabe almost 2 years ago

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.

#8 Updated by Thomas Sawyer almost 2 years ago

=begin
Oh, thanks Shyouhei. That is very helpful breakdown. So I infer then, # 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

#9 Updated by Thomas Sawyer almost 2 years ago

=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

#10 Updated by Yutaka HARA over 1 year ago

  • Target version changed from 2.0.0 to next minor

#11 Updated by Thomas Sawyer over 1 year ago

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.

Also available in: Atom PDF