> From: ale / crimson.propagation.net [mailto:ale / crimson.propagation.net] [...] > > Someone presented a wild idea here not so long ago. IIRC he queried I think, this ``someone'' was me > whether it would be useful to extend OO concepts to other direction than > usually though. Namely having more than one receiver of a message. > > In this case a function with two parameter could still exhibit the natural > OO order of syntax > > value = (y,x).atan2 the notation (<y,x>).atan2 is sometimes used for this ... this would work well with Ruby's scanning rules too I believe ... [...] > Nevertheless, while I doubt the idea was very original, it's surely > interesting one. it isn't original at all - the OO-kraut calls this multiple-dispatch - and I find this notion much more obvious and natural than the singleton notion. Anyway consider the following is as way off tangent ramblings since Matz does not like multiple dispatch anyway (and I don't really know what I am writing about anyway;-) > | value = (y,x).atan2 > > No, please. > In general relavant google keywords for this stuff are (Cecil singleton multiple dispatch.) This how multiple dispatch might work in Ruby: Note I am not suggesting this (it is seems too complicated) but would certainly prefer something like this over simple minded type-based overloaded functions - in fact consider this as a warning why type-based overloaded functions do not fit at all into the current single-dispatch ruby object model. Let's you already defined your classes A,B (in the example A=B= Float) you could define (otherwise you would get an exception) as basic definition, short for X = Class::IsPair(A,B) class X IsPair A,B # at this point you have access to mself(0), mself(1) - # and the double Object self - i.e. # self == (<mself(0),mself(1)>) def atan2 #do calculation with mself(0),mself(1) return arctan # normal object end def polar #do calculation with mself[0],mself[1] return (<arctan,radius>) # double object which would be end # different from the array [arctan,radius] end (more generally this could be class X IsTuple A0,A1,A2,A3) This definition creates the double class Object X - and would work the following way - assuming that A,B = Float,Float a, b = 2.0,3.1 # creates the two normal objects a,b x = (<a,b>) # creates double Object x atan = x.atan2 # create normal object atan pol = x.polar # create double object pol The only way normal objects could access the components of double objects would be over accessor methods #mself defined in the double object Object2 class. It would probably useful to add a method which flattens the double object and include short-cuts for mself(0),mself(1) class Object2 IsPair Object,Object def mself0 mself(0) end ... def to_obj; return mself[0],mself[1] # normal array end def mtype return # an array of the multi-type would be end # [Object,Object] end The real interesting point is of course the multi-method lookup - the point where type-based overloaded functions are both slow and muddled with Koenig lookups etc.. (the following leaves out the question on how to generalize module inclusion but this can probably be done coherently as well) The basic strategy probably should be lexicographic over the mtype components in our example an double object since this strategy is simple and coherent. In our example this would be [Float,Float],[Float,Numeric],[Float,Object], [Numeric,Numeric] ,..., [Object,Object] This strategy is also very slow in long object paths (particularly in nested name-spaces) so have you to restrict your search path to the double types which actually have been created - in practice (ops theory;-) this boils to re-computing the ``mtype-succ''every time a new double type is instantiated but this can be done rather efficiently. Anyway in your example the search path would as short as [Float,Float],[Object,Object] not too bad. What is really interesting what happens if you allow the creation of multi-types where some of the components are singleton types - you probably could define functions like functional type languages do ... Christoph