Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

syntax: multi vs. method

7 views
Skip to first unread message

Jonathan Lang

unread,
Nov 17, 2003, 9:22:22 PM11/17/03
to perl6-l...@perl.org
My apologies for the break in the chain of responses; I lost your reply
before I could reply to it, and had to retrieve it from the list archives.

Luke Palmer wrote:
> Well, "multi" is no longer a declarator in its own right, but rather a
> modifier. Synopsis & Exegesis 6 show this.

I don't know about Exegesis 6, but Synopsis 6
(http://dev.perl.org/perl6/synopsis/S06.html) is still showing multi to be
a declarator on par with sub, method, rule, and macro.

> I think this makes things even clearer, and has a fine-grained but
> elegant control over the "scope" of the routine.

Agreed; I'd like something like this to be implemented.

> This easily allows for "multisubmethods" and even "multimacros"
> (provided you have yourself a polymorphic object at compile time).

For the record, subs never have invocants as currently described - so you
could easily say that any sub that has an invocant is actually a
submethod:

sub touch ($a: $b) {...}

would be synonymous with:

submethod touch ($a: $b) {...}

> I also think it's important to say "multi" explicitly every time you
> mean it. It allows the compiler to warn you when you're just being
> stupid about scoping as opposed to actually wanting to overload the
> routine. From a design perspective, it makes it clear that this method
> introduces logical control-flow in addition to performing a task.

That's probably good programming advice; but it should remain advice
rather than being a requirement.

If you allow the distinction between a method and a multimethod to be
determined implicitly, you can, if you choose, ignore the "submethod" and
"multi" keywords altogether with minimal loss of capabilities:

submethod touch ($a) {...}
multi watch ($a, $b) {...}

would be equivelent to

sub touch ($_: $a) {...}
method watch ($a, $b:) {...}

=====
Jonathan "Dataweaver" Lang

__________________________________
Do you Yahoo!?
Protect your identity with Yahoo! Mail AddressGuard
http://antispam.yahoo.com/whatsnewfree

Luke Palmer

unread,
Nov 18, 2003, 8:58:20 AM11/18/03
to Jonathan Lang, perl6-l...@perl.org
Jonathan Lang writes:
> My apologies for the break in the chain of responses; I lost your reply
> before I could reply to it, and had to retrieve it from the list archives.
>
>
> Luke Palmer wrote:
> > Well, "multi" is no longer a declarator in its own right, but rather a
> > modifier. Synopsis & Exegesis 6 show this.
>
> I don't know about Exegesis 6,

Then you should probably read it. It is the most recent of the
documents, so what it says is closest to the current thinking. Plus,
it's a fun read.

> but Synopsis 6 (http://dev.perl.org/perl6/synopsis/S06.html) is still
> showing multi to be a declarator on par with sub, method, rule, and
> macro.

Now that I look, yes, that's true. It's wrong.

> > I think this makes things even clearer, and has a fine-grained but
> > elegant control over the "scope" of the routine.
>
> Agreed; I'd like something like this to be implemented.
>
> > This easily allows for "multisubmethods" and even "multimacros"
> > (provided you have yourself a polymorphic object at compile time).
>
> For the record, subs never have invocants as currently described - so you
> could easily say that any sub that has an invocant is actually a
> submethod:
>
> sub touch ($a: $b) {...}
>
> would be synonymous with:
>
> submethod touch ($a: $b) {...}

Hmm. Well, that depends on whether calling works like it does in Perl
5. That is, given:

multi sub touch (Foo $a: $b) {...}

Is this legal:

my $x = new Foo;
$x.touch;

I haven't been able to deduce this.

> > I also think it's important to say "multi" explicitly every time you
> > mean it. It allows the compiler to warn you when you're just being
> > stupid about scoping as opposed to actually wanting to overload the
> > routine. From a design perspective, it makes it clear that this method
> > introduces logical control-flow in addition to performing a task.
>
> That's probably good programming advice; but it should remain advice
> rather than being a requirement.

Spoken like a true Perl programmer :-)

I don't see the win in losing the C<multi> keyword though. Sure, there
are 5 fewer characters, but declarations aren't a place where concise
and terse are synonymous. IMO, a colon is too small a character for
such a large distinction. Misunderstanding the rule slightly can lead
to overriding instead of overloading... reminds me of C++ [1].

> If you allow the distinction between a method and a multimethod to be
> determined implicitly, you can, if you choose, ignore the "submethod" and
> "multi" keywords altogether with minimal loss of capabilities:
>
> submethod touch ($a) {...}
> multi watch ($a, $b) {...}
>
> would be equivelent to
>
> sub touch ($_: $a) {...}
> method watch ($a, $b:) {...}

Luke

[1] While I haven't the hatred for C++ that quite a few people on this
list do, I definitely consider it an "advanced" language, by which I
mean there are subtle variants in the rules that cause wildy different
behaviors. Beginners (and intermediates) still struggle with this one:

class Base {
public:
virtual int num() const { return 10; }
}

class Derived : public Base {
public:
int num() { return 20; }
}

int main() {
Base* b = new Base; Base* d = new Derived;
cout << b->num() << endl; // 10
cout << d->num() << endl; // 10 !!
}

Now why the heck did the call to d->num() return 10??!!! Because they
missed a C<const> in the overriding of num(), hiding it instead. This
is precisely what would happen if you missed a colon in adding a
multimethod. Sorry, I don't want to inflict this kind of pain on Perl
programmers.

Jonathan Lang

unread,
Nov 18, 2003, 6:20:17 PM11/18/03
to Luke Palmer, perl6-l...@perl.org
Luke Palmer wrote:

> Jonathan Lang writes:
> > Luke Palmer wrote:
> > > Well, "multi" is no longer a declarator in its own right, but rather
> > > a modifier. Synopsis & Exegesis 6 show this.
> >
> > I don't know about Exegesis 6,
>
> Then you should probably read it. It is the most recent of the
> documents, so what it says is closest to the current thinking. Plus,
> it's a fun read.

OK; I just finished it. Apparently, there's a distinction between
"multimethod" and "multi sub", and it's a distinction which renders one of
my points invalid. A multimethod has multiple invocants and handles
dispatching based on the types of said invocants. A "multi sub" has no
invocants; instead, it has a subset of its parameters (seperated from the
others by a colon) which it uses for dispatching purposes. As such,
"multi sub ($a: $b) {...}" already has meaning, in that dispatching will
be decided strictly off of $a's type.

So the following three declarations cover very similar (but not quite
identical) things:

multi sub call ($a: $b) {...}
submethod invoke ($a: $b) {...}
method check ($a: $b) {...}

All three of these use multiple dispatching. The only distinctions are
that "invoke" and "check" can be called using method-like syntax, whereas
"call" cannot; and "check" pays attention to inheritence, whereas "call"
and "invoke" do not.

In the case of multiple "dispatch variables", the situation gets a bit
messier as I understand you:

multi sub call ($a, $b: $c) {...}
multi submethod invoke ($a, $b: $c) {...}
multi method check ($a, $b: $c) {...}

Why do we suddenly need to append the "multi" keyword to "submethod" and
"method"? Because it has a different meaning for method or submethod:
with "sub", the "multi" keyword means "use multiple dispatching", and so
we use it any time that we have one or more "dispatch parameters"; with
"submethod" and "method", multiple dispatching is assumed and the keyword
means "use more than one invocant".

IMHO, we should choose one of these definitions for "multi" and stick with
it. If you go with "use multiple dispatching", multi becomes redundant
for method and submethod; if you go with "allow more than one dispatch
parameter", then you ought to be able to declare a multiply dispatching
sub with a single dispatch parameter without using the multi keyword.
Personally, I think that the first definition is the less confusing one.

If you choose it, you'll never have need to use the "multi" keyword in
conjunction with "method" or "submethod", restricting its use in practice
to cases where multiple dispatching doesn't normally occur (subs and
macros, mostly). In those cases, one _could_ implicitly determine whether
the sub or function is multiply dispatched by looking for the colon in the
signature; but I tend to agree in these cases that requiring the "multi"
keyword might be a good idea.

Damian Conway

unread,
Nov 18, 2003, 9:50:19 PM11/18/03
to perl6-l...@perl.org
Jonathan Lang wrote:

> multi sub call ($a, $b: $c) {...}
> multi submethod invoke ($a, $b: $c) {...}
> multi method check ($a, $b: $c) {...}
>
> Why do we suddenly need to append the "multi" keyword to "submethod" and
> "method"?

So the compiler knows we really did mean for that (sub)method to be multiply
dispatched, and didn't just accidentally put the colon in the wrong place.


> with "submethod" and "method", multiple dispatching is assumed

No. Regular (sub)methods are singly dispatched.


Damian

Larry Wall

unread,
Nov 18, 2003, 9:53:13 PM11/18/03
to perl6-l...@perl.org
I think most everyone is missing the new simplicity of the current
conception of "multi". It's now completely orthogonal to scoping
issues. It merely says, "I'm putting multiple names into a spot
that would ordinarily demand a unique name."

In other words, what a name means in a given scope is a kind of
invariant--there's no magic hocus pocus in which multimethod dispatch
suddenly "steals" calls from ordinary method dispatch.

This is actually more powerful than the usual multimethods. To get
the usual behavior of multimethods in other languages, you have to
explicitly declare the multimethods in global space:

multi sub *add( Foo $foo, Bar $bar );

If you write:

multi sub add( Foo $foo, Bar $bar );

then the current package has multiple add routines, but they aren't global.

If you write:

multi my sub add( Foo $foo, Bar $bar );

then the current *lexical* scope has multiple add routines!

If you write:

multi method add( $self: Foo $foo, Bar $bar );

then there are multiple add methods in the current class. Note the
invocant is not optional in this case. Also, there's an implied
second colon after $bar, indicating the end of the arguments to be
considered for multi dispatch. (You can put as many colons as you
want in any multi declaration--each subsequent colon indicates that
the preceding additional argument or arguments are to be used as
"tie breakers, just as Foo and Bar are being used for tie-breaking
in the method above.) Likewise for submethods:

multi submethod add( $self: Foo $foo, Bar $bar );

In essence, the compiler could implement "multi" by taking any such
set of identically named routines and implementing them as a single
routine with switching logic to tell the types apart.

One ramification of all this is that "true" multimethods must always
be called as subroutines, not as methods.

I hope this clarifies things a bit. Well, more than a bit...

Larry

Joe Gottman

unread,
Nov 18, 2003, 10:04:20 PM11/18/03
to perl6-l...@perl.org

----- Original Message -----
From: "Jonathan Lang" <datawe...@yahoo.com>
> So the following three declarations cover very similar (but not quite
> identical) things:
>
> multi sub call ($a: $b) {...}
> submethod invoke ($a: $b) {...}
> method check ($a: $b) {...}
>
> All three of these use multiple dispatching. The only distinctions are
> that "invoke" and "check" can be called using method-like syntax, whereas
> "call" cannot; and "check" pays attention to inheritence, whereas "call"
> and "invoke" do not.
>

Also, I assume that invoke and check will have access to $a's private
data members and methods, while call will not.

Joe Gottman


Luke Palmer

unread,
Nov 19, 2003, 12:15:13 AM11/19/03
to perl6-l...@perl.org
Larry Wall writes:
> If you write:
>
> multi method add( $self: Foo $foo, Bar $bar );
>
> then there are multiple add methods in the current class. Note the
> invocant is not optional in this case. Also, there's an implied
> second colon after $bar, indicating the end of the arguments to be
> considered for multi dispatch. (You can put as many colons as you
> want in any multi declaration--each subsequent colon indicates that
> the preceding additional argument or arguments are to be used as
> "tie breakers, just as Foo and Bar are being used for tie-breaking
> in the method above.)

So what is the, ahem, submethod for determining the dispatch within the
tie-breaking cascades? A simple sum of differences? Cartesian
distance?

Luke

> Larry

0 new messages