From: "David A. Black" Date: 2008-07-01T23:18:59+09:00 Subject: Re: Hash#select returns an array but Hash#reject returns a hash... Hi -- On Tue, 1 Jul 2008, Rick DeNatale wrote: > On Tue, Jul 1, 2008 at 8:48 AM, David A. Black wrote: > >> Hi -- >> >> >> On Tue, 1 Jul 2008, Srijayanth Sridhar wrote: >> >> >>>> that will change in newer version of ruby, eg ruby1.9 >>>> >>>> irb(main):015:0> RUBY_VERSION >>>> => "1.9.0" >>>> irb(main):016:0> a=Hash.new >>>> => {} >>>> irb(main):017:0> a[1]=2 >>>> => 2 >>>> irb(main):018:0> a[2]=2 >>>> => 2 >>>> irb(main):019:0> a[3]=4 >>>> => 4 >>>> irb(main):020:0> a.select { |key,value| value > 2 } >>>> => {3=>4} >>>> irb(main):021:0> a.reject { |key,value| value <= 2 } >>>> => {3=>4} >>>> >>>> kind regards -botp >>>> >>>> >>>> >>> Thanks. >>> >>> So this is just some sort of artefact/legacy code that never got changed? >>> >> >> You can actually make a case that select and reject are not exactly >> symmetrical operations. Imagine a line of people: >> >> >> Joe John Joan David Jim Jenny Jeff Matz >> >> If I tell everyone in the line whose name does not begin with J to >> step backwards (reject), the original line is smaller but it's still >> the same line. >> >> If I tell everyone whose name *does* begin with J to step forwards >> (select), I've got a new line of J people. > > > I'm having a hard time making the connection between this analogy and the > methods. > > In the first case one could say that we end up with two lines, the > 'original' one and the line of rejects. > > But first of all, x.reject leaves x alone so the original 'line' is > unchanged. > > And why can't we see your select example exactly the same way, except with > the resultant line of 'selects' just closer to you. > > >> "Same line" and "new line" don't necessarily map to "same object" and >> "new object" in Ruby (since the post-reject hash is a different hash). >> But it suggests that there's a difference, arguably, between select >> and reject, in terms of the formal disturbance of the object, which in >> turn makes it easier to understand why select would return objects in >> a different container, while reject would leave the container in the >> same form but just contain fewer things. > > > Except that both select and reject leave the original container the same. > The analogy might be more apt for reject! and select! (if the latter method > existed). It's specifically not about the exact objects, though. As I said, "same line" in this model doesn't map to "same object". Rather, the analogy has to do with types of structure or container. Here's another, perhaps better analogy. You've got a shelf of books, and you've got an empty box. You select some books from the shelf, and put them in the box. Now you've got two structures: a shelf, and a box. If you were describing this operation, you'd say: "I selected some books and put them in a box." The box of books is the result of the operation, and is structurally different from the shelf. The point is not that this is the only way it can be done, but that it *can* be done this way. It's reasonable to select from a collection into something that is not only a different collection, but a different container type. Now, if you do it reject-wise, you take the books you don't want and throw them out the window. The box never enters into it. You're not selecting, so you don't care about observing or measuring the books that you're removing from the shelf. And the shelf is still a shelf. There's no new type of container involved, just the same type of container with different contents. The reject operation does not imply the transfer of objects to a different type of container. Also, the fact that Ruby can do this in terms of duplicate objects, rather than in place, isn't relevant. The change or conservation of the container type is what's important. That's all I'm saying :-) And thereafter, to make sense of the new 1.9 behavior, all you have to do is decide that instead of a box, you're putting the selected books on another shelf. Again, this has nothing to do with the identity of objects vs. copies. It's about the proliferation (or not) of structures. >> However, that doesn't mean it's bad for select to return a hash (which >> it does, as was mentioned, as of 1.9). Just that the behavior of one >> doesn't necessarily imply the behavior of the other. >> > > The real change, it seems to me is that pre 1.9 the Ruby enumerator methods > had/have a preference for returning arrays rather than an instance of the > same class as the receiver, whereas 1.9 seems to be shifting to a preference > for returning an instance of the same class as the receiver where that makes > sense. Yes, that's clearly the change. I wasn't talking about the change, though; I was suggesting a model for understanding why the pre-change way might not have been as irrational as has sometimes been suggested. It's all moot as of 1.9. David -- Rails training from David A. Black and Ruby Power and Light: Intro to Ruby on Rails July 21-24 Edison, NJ Advancing With Rails August 18-21 Edison, NJ See http://www.rubypal.com for details and updates!