Dirk Traulsen
1/30/2008 1:08:00 PM
Am 30 Jan 2008 um 4:20 hat Robert Klemme geschrieben:
> 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?
(...)
> > 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. :-)
That's true. So this has to be proven by implementation.
> > 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?
Below I put a few examples. I'm sure if I would really dive into the
standard lib, there might be better ones, but these came to my mind.
h1 = { "a" => 20, "b" => 10 }
h2 = { "b" => 25, "c" => 30 }
#Enumerable#grep
p h1.grep(Array) #=> [["a", 20], ["b", 10]]
p h1.grep(Array) {|(k,v)| v } #=> [20, 10]
#Hash#merge
p h1.merge(h2) #=>{"a"=>20, "b"=>25, "c"=>30}
p h1.merge(h2){|k,ov,nv| nv=ov if ov<nv} #=>{"a"=>20, "b"=>10, "c"=>30}
#Hash#fetch
p h1.fetch("z") rescue p $! #=> #<IndexError: key not found>
p h1.fetch("z") {|v| 'wrong key'} #=> "wrong key"
#Hash#sort
p h1.sort #=> [["a", 20], ["b", 10]]
p h1.sort {|(k,v),(k2,v2)| v <=> v2} #=> [["b", 10], ["a", 20]]
> 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.
It does not feel orthogonal for me. This is a combination, true, but I
would not call it orthogonal.
In real life most tasks are combinatory.
Ruby has a lot of constructs which mimic human thinking and use this
for a more intuitive access to programming.
Intuitively for me
hash.keys {|k,v| v > 200 }
was the same as
hash.select {|k.v| v > 200 }
Just the returned values differ.
Hash#select gives you the chosen key-value pairs in an array and
Hash#keys/values with a block only the chosen keys or values.
(...)
> > 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.
> :-)
Well, it seems it is more of a private debate. I'm a little
disappointed by this lack of interest. Do you think I should have
posted it to ruby-core?
> Dirk, I am glad that once again there is an interesting discussion.
> Thanks for that!
Thanks a lot for your comments.
Kind regards
Dirk