From: Robert Klemme Date: 2008-01-30T04:20:03+09:00 Subject: Re: Proposal/RFQ: Hash#values/keys with block On 29.01.2008 18:29, Dirk Traulsen wrote: > Am 29 Jan 2008 um 22:50 hat Robert Klemme geschrieben: > >> I am waiting to see whether this is generally needed. As far as I >> remember this has not been suggested before. If there is no >> overwhelming request for this I opt for not making this standard. > > Why make it standard? > > 1. No regression > Until now, a block after Hash#keys/values is just ignored. > So, there would be no regression for old code. True. > 2. No clutter > As it is just an additional behaviour of exiting methods, there would > be no new methods cluttering the standard library. That's true. However, there are also other things to consider: often it is more flexible to spread functionality across different methods. So, lesser methods is not a value per se. > 3. Speed > I think that this will not slow down ruby as a whole, but I'm sure that > > hash.values {|k,v| v % 2 == 0 } > > would be definitely faster than > > hash.select {|k,v| v % 2 == 0 }.map {|k,v| v} > > especially with big hashes, because you make only one array directely, > not two and don't have to call map additionally. You would be surprised to see how fast seemingly more complex bits of code often are. I myself have been surprised in the past. > And let us not begin about inject and speed.. See? #inject can often be used to avoid multiple traversals but yet often a combination with #map is faster. :-) > 4. Rubyness > This is difficult to describe, but one point I really, really like > about Ruby is blocks. There are a lot of methods in the standard > library which use blocks to 'finetune' the method. > Use them pure and you get all of it. > Or use them with a block and you get a subset or a modified result. I am not sure I agree here. If you take #each or #select, these do not make any sense without a block so the block is certainly not fine tuning the method. What examples do you have in mind? My soft point here is, that it somehow feels odd to combine two completely orthogonal things (key extraction and entry selection) in a single method to me. > I got so used to it, that I first wrote Hash#keys with a block without > looking in ri before. This is interesting: it never occurred to me to use #keys with a block. Off the top of my head I cannot remember a situation where I needed selection and key extraction at the same time (which does not mean I never did it). > I think this would fit perfectly in, as it is, at least for me, typical > Ruby syntax. > > 5. Beauty > I really like inject. (Though maybe not as much as you do, Robert. :) ) LOL > But if I compare > > hash.values {|k,v| k.size == 1 } > > with > > hash.select {|k,v| k.size == 1 }.map {|k,v| v} > hash.inject([]) {|ks,(k,v)| ks << v if k.size == 1; ks} > > then I think it is obvious, why I really prefer the first variant. > It is direct, short and clear. Less characters, but more obvious. I find the #select / #map solution more obvious. If I was writing the functionality of #keys with a block, I'd probably name the method #select_keys. > That's what I love about Ruby > > ======= > > Robert, don't you think it would fit nicely in the standard lib? I would not say that it does not fit but I am not totally convinced. I am trying to employ public debate to find out the best solution. :-) > What do the others think? > Please tell me your opinion and give your +1/-1 to the extension of > Hash#key/values in the standard lib! Dirk, I am glad that once again there is an interesting discussion. Thanks for that! Kind regards robert