> 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