From: "trans. (T. Onoma)" Date: 2004-10-07T23:11:11+09:00 Subject: Re: Range behavior (Re: [RCR] New [] Semantics) matz wrote: | > Your opinion makes sense. What do you thinks is the best way to fix? | > Or maybe we first need to define the problem to fix to evaluate the fix. Let me think on it some more. It's actually not a simple problem once you really start to think about it (see below) --but we need a simple fix. --- On Thursday 07 October 2004 05:04 am, Martin DeMello wrote: | > |Not at all. This is something particular to a Range so why overload | > | #include? with that function? Doing so can cause duck-typing problems. | > | To me member? and include? are just different names for the same thing | > | and should stay that way. | > | If I've followed along properly, the problem is as follows: Enumerable | sets up a contract that include? is a synonym for member?, in much the | same way that map? is a synonym for collect?. By changing one but not | the other, Range is breaking that contract, which might affect duck | typed code. (Incidentally, I see this as an excellent argument against | having "officially blessed" synonyms at all, but that's another | argument.) Yes, in a sense that is right. But the issue is two fold. The 1st is the issue with Range itself. The 2nd, broader and encompassing the 1st, is synonym overriding --which occurs in a number of places throughout the libs. To properly address the 1st I think it helps to look at the 2nd. A good example of this is Object#=== : Case Equality—For class Object, effectively the same as calling #==, but typically overridden by descendents to provide meaningful semantics in case statements. Indeed, a few Classes redefine this. The most obvious is Regexp which make :=== the same as :=~. Less obvious is Range itself which makes it the same as :member? Or is it include? --between? --ah ha, that's a catch, isn't it! Given this lets look directly at 1st issue along with what you said. (We can come back to Override question later.) | Of course, the underlying problem may be that range should not include | Enumerable at all, or that ContinuousRange and DiscreteRange should be | two entirely differnt objects, with only the latter including | Enumerable. Then we could have a separate RangeLike mixin, with a | contains? operator that does bounds testing, and the DiscreteRange would | mix in Enumerable and hence get include? (and member?) with discrete | semantics. At first, I didn't think it mattered, but b/c of what I just touched on above I see you do have a very good point --there is an important difference. As it would be imprudent to discount the need for one use over the other, somehow we need to have both. Off the cuff I see two options: 1) An internal flag: discrete vs. continuous 2) Or two separate classes, as you suggest. But there is more to it... This becomes increasing interesting (or frustrating depending on your slant) when we consider the further advantages of having a NumericRange --notice that its advantage is specific to discreteness (member modulo). But all Ranges are based on succ and are therefore by definition discrete --only Numeric ranges can be Continuous. Consider further how succ determines successive members --a Range is an indeterminate ordered set built by iteration. Oddly one defines a Range with a first and last argument, but iterations are supposed to be defined by a seed (first) and the number of successive iterations. And there is good reason for this: there is no way to be sure that any given _last_ is a member of the set! Look at this: class ShrinkyDink def initialize(x); @x = x.to_i; end def succ; @x - 1; end def <=>(b); @x <=> b; end end rng = ShrinkyDink.new(0)...ShrinkyDink.new(100) Not only is ShrinkyDink.new(100) not a member of the range, but nothing "inbetween" the two is either! I'm going to stop here for now. I have more to offer, but I want to work on it a little bit more before I go into it. Also... | Separating Range functionality into a mixin might also make it easier to | get goodies like negative-stepping and infinite ranges. Could you elaborate on this more? T.