# -----Original Message-----
# From: Ken Fox [mailto:[EMAIL PROTECTED]]
# Sent: Saturday, September 01, 2001 9:44 AM
# To: Me
# Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED]; Michael G Schwern; Dan
# Sugalski
# Subject: Re: Multiple-dispatch on functions
...
# The one thing I'm curious about is whether different syntactic
# conventions affect the dispatcher or whether this is all just
# sugar for a single dispatch. Perl 5 uses several different
# sub call syntaxes:
#
#   $obj->method(...)
#   method $obj ...;
#   function($x, ...);
#
#   $obj->Scope::method(...)
#   Scope::method $obj ...;
#   Scope::function($x, ...);
#
# Does the C style dispatch differently from the C++ style?
#
# I'd expect indirect object syntax to dispatch like C++
# syntax since indirect object syntax is just sugar. But is
# it possible to tell the difference between C style and
# indirect object style for functions of arity 1?
#
# IMHO it would be very nice if everything was just sugar
# for "function($x, ...)". It would be harder to define
# the nearest multi-method, but at least we wouldn't
# have to worry about different dispatchers kicking in when
# we didn't expect them to.

I think what we have to do is separate dispatch into two steps.  The
first should identify the name of the function being called and run
through all the packages it might be in, passing the name and the
parameters to the second step.  The second step should see if a function
by that name exists in the package passed in.  The logic goes something
like this for a simple function call:

        sub first_step_normal {
                my($function, @params)=@_;
                my($package, $name)= $function =~ /^(.*)::(\w+)$/
                $package ||= "main";
                $name ||= $function;

                if($address=second_step($package, $name, @params)) {
                        return &$address(@params);
                } elsif($address=second_step($package, "AUTOLOAD", @params)) {
                        $AUTOLOAD=$name;
                        return &$address(@params);
                }
                else {
                        die "subroutine $name not found in package $package";
                }
        }

For a method call, it's more complicated:

        sub first_step_method {
                my($function, @params)=@_;
                my($package, $name)=$function =~ /^(.*)::(\w+)$/;
                $package ||= ref $params[0];
                $name ||= $function;

                @packages=($package, get_all_parents_in_traversal_order($package));

                for(@packages) {
                        if($address=second_step($_, $name, @params)) {
                                return &$address(@params);
                        }
                }

                for(@packages) {
                        if($address=second_step($_, "AUTOLOAD", @params)) {
                                $AUTOLOAD=$name;
                                return &$address(@params);
                        }
                }

                die "method $name not found for object of type $package";
        }

(Both of these examples leave out complications involving the package
$AUTOLOAD is in.)

The second step takes care of resolving the address of the function; it
handles picking which (if any) of the prototypes available for the
method is appropriate for those parameters.  Its implementation is left
as an exercise to the reader.  :^)

--Brent Dax (who finds it very amusing that the spell checker tried to
change Sugalski to Sealskin)
[EMAIL PROTECTED]

"...and if the answers are inadequate, the pumpqueen will be overthrown
in a bloody coup by programmers flinging dead Java programs over the
walls with a trebuchet."

Reply via email to