From: Daniel Carrera Date: 2003-08-01T03:43:35+09:00 Subject: Re: Changing ==,>,<, etc I think I have an idea. I'm not sure about the implementation details: Example: 3 < any(1,2,4) 1) Create a Disjunction#<=> and mixin Enumerable so that you can write things like: any(3) < any(1,2,4) all(3) > any(1,2,4) 2) Create a Disjunction#coerce method so that the line: 3 < any(1,2,4) Is turned into the line: all(3) > any(1,2,4) # It doesn't matter if it's any(3) or all(3). When Ruby sees "3 < any(1,2,4)" it'll look for Fixnum#coerce for help. When it doesn't help, it'll look at Disjunction#coerce. Or, at least that's what I think. The Disjunction#coerce would be written somewhat like this: class Disjunction # WARNING: No error checking. def coerce(other) return all(other), self end end Cheers, Daniel. On Fri, Aug 01, 2003 at 03:22:36AM +0900, Nathan Weston wrote: > The latest Perl exegesis > (http://www.perl.com/pub/a/2003/07/29/exegesis6.html?page=4) > introduces "junction types", which are really cool. > In short, you can do expressions like (a == any(1,2,3)) or (a > > all(1,2,3)) instead of (a == 1) or (a == 2) or (a == 3), etc. > > So of course, I immediately set out to do this in ruby. So, I whipped > up a Disjunction class, and the any() function for syntactic sugar, > and soon I could do: > > # 1 == any(1,2,3) > true > # 4 == any(1,2,3) > false > > And all was well. But then I hit a snag: > # 1 < any(1,2,3) > ERR: (eval):1:in `<': Disjunction can't be coerced into Fixnum > > Fixnum#== seems to be smart enough to call Disjunction#==, which gets > the behavior I want. Unfortunately, Fixnum#< is not, and neither are > most of the <,>,== methods in the various built-in classes (i.e. > String#== and Array#== both return false for any Junction class). > > Of course, with ObjectSpace and module_eval, I can redefine everyone's > comparison methods to work properly, but this is kind of ugly. Also, > if someone defines a new class after after I have done my ObjectSpace > hack, they have to explicitly write their comparison methods to know > about Junctions. > > Is there a better way to do this? > > If there's not a better way, should there be? > I was thinking that perhaps all comparison methods should have a > similar semantics, along the lines of: > > class Foo > def ==(obj) > if obj.is_a?(Foo) > #I know how to compare myself to other Foo objects, > #so I will do so > return somevalue > else > #I don't know how to compare myself to non-Foo objects, > #but maybe they know how to compare themselves to me -- > #let's give them a chance > return (obj == self) > end > end > end > > Or at least, that's the basic idea. There also needs to be some way to > bail out when neither class knows how to compare to the other -- > either by returning false or throwing an exception. > > If all comparison methods worked this way, I could implement my > Junction classes with no hacks, since objects that didn't know > anything about Junctions would just let the Junction do the > comparison. -- Daniel Carrera | PGP: 6643 8C8B 3522 66CB D16C D779 2FDD 7DAC 9AF7 7A88 Math PhD. UMD | http://www.math.umd.edu/~dcarrera/pgp.html * * * * * Weekly Smile * * * * * * * * * * * * * * * * * * * * * * * * Sign in a hotel in Athens: Visitors are expected to complain at the office between the hours of 9 and 11 A.M. daily. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *