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

Multimethod/multisub thought...

6 views
Skip to first unread message

Piers Cawley

unread,
Jan 24, 2003, 2:30:32 AM1/24/03
to perl6-l...@perl.org
In my quest to eliminate as many explicit conditionals from my code as
possible, I found myself wondering if Perl 6's multidispatch mechanism
would allow one to write:

sub gmttime ( $time = time() ) is in_scalar_context {
strftime( $perls_default_time_format, $time );
}

sub gmttime ( $time = time() ) is in_list_context {
...
}

where 'in_scalar_context' and 'in_list_context' are place holders for
better syntax.

Thoughts?

Dan Sugalski

unread,
Jan 24, 2003, 2:46:03 AM1/24/03
to Piers Cawley, perl6-l...@perl.org

There's been some discussion of this, doing MMD based on return type
as well as the parameters. It's definitely cool, but IIRC it's
potentially a bit of a pain, since context is odd in spots.
--
Dan

--------------------------------------"it's like this"-------------------
Dan Sugalski even samurai
d...@sidhe.org have teddy bears and even
teddy bears get drunk

Austin Hastings

unread,
Jan 24, 2003, 10:51:34 AM1/24/03
to Piers Cawley, perl6-l...@perl.org

I think that if RFC 21 is approved (general-purpose C<want()>, with
smartmatch flavors) the information to dispatch these should be
available.

OTOH, it also seems like this is asking for trouble, MMD-wise.

=Austin

Dan Sugalski

unread,
Jan 24, 2003, 12:07:58 PM1/24/03
to Piers Cawley, perl6-l...@perl.org
At 7:30 AM +0000 1/24/03, Piers Cawley wrote:
>In my quest to eliminate as many explicit conditionals from my code as
>possible, I found myself wondering if Perl 6's multidispatch mechanism
>would allow one to write:

Okay, I think I remembered the problem. Assume the following:

list bar(int); # bar takes an int, returns a list
scalar bar(int); # bar takes an int, returns a scalar

and also assume the following:

xyzzy(scalar); # xyzzy takes a scalar
xyzzy(list); # xyzzy takes a list

and then we make the call:

xyzzy(bar(1));

Which bar do we call? And which xyzzy?

Austin Hastings

unread,
Jan 24, 2003, 1:02:13 PM1/24/03
to Dan Sugalski, Piers Cawley, perl6-l...@perl.org

--- Dan Sugalski <d...@sidhe.org> wrote:
> At 7:30 AM +0000 1/24/03, Piers Cawley wrote:
> >In my quest to eliminate as many explicit conditionals from my code
> as
> >possible, I found myself wondering if Perl 6's multidispatch
> mechanism
> >would allow one to write:
>
> Okay, I think I remembered the problem. Assume the following:
>
> list bar(int); # bar takes an int, returns a list
> scalar bar(int); # bar takes an int, returns a scalar
>
> and also assume the following:
>
> xyzzy(scalar); # xyzzy takes a scalar
> xyzzy(list); # xyzzy takes a list
>
> and then we make the call:
>
> xyzzy(bar(1));
>
> Which bar do we call? And which xyzzy?

In theory, if there's a return type expected, we could use that as the
final arbiter.

If not, but "if it looks like a scalar" ...

xyzzy(bar 1); # Scalar
xyzzy(bar(1)); # Scalar
xyzzy(bar((1))); # List?
xyzzy(bar(list(1))); #List
xyzzy(bar(scalar(1))); # Scalar

Optionally, we whinge about "ambiguous method invocation at line ..."
and punt; requiring the user to cast or establish context.

Welcome to namespace hell. Woo-hoo! It's just like the C++, only with
one more dimension to consider.

=Austin

Brent Dax

unread,
Jan 24, 2003, 1:15:48 PM1/24/03
to Dan Sugalski, Piers Cawley, perl6-l...@perl.org
Dan Sugalski:
# At 7:30 AM +0000 1/24/03, Piers Cawley wrote:
# >In my quest to eliminate as many explicit conditionals from
# my code as
# >possible, I found myself wondering if Perl 6's multidispatch
# mechanism
# >would allow one to write:
#
# Okay, I think I remembered the problem. Assume the following:
#
# list bar(int); # bar takes an int, returns a list
# scalar bar(int); # bar takes an int, returns a scalar
#
# and also assume the following:
#
# xyzzy(scalar); # xyzzy takes a scalar
# xyzzy(list); # xyzzy takes a list
#
# and then we make the call:
#
# xyzzy(bar(1));
#
# Which bar do we call? And which xyzzy?

This is also a problem with using want().

If we don't provide wants_scalar/wants_list, someone will build it with
want(), so we might as well try to address it. I suggest that want()
return a special value when the calling context is ambiguous, and any
wants_scalar/wants_list property be designed to accommodate this
(probably by specifying which one should be the default).

--Brent Dax <bren...@cpan.org>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)

>How do you "test" this 'God' to "prove" it is who it says it is?
"If you're God, you know exactly what it would take to convince me. Do
that."
--Marc Fleury on alt.atheism


Jonathan Scott Duff

unread,
Jan 24, 2003, 1:07:13 PM1/24/03
to Austin Hastings, Dan Sugalski, Piers Cawley, perl6-l...@perl.org

Strange. I think parameters to subroutines are in list context unless
stated otherwise.

-Scott
--
Jonathan Scott Duff
du...@cbi.tamucc.edu

Dan Sugalski

unread,
Jan 24, 2003, 1:25:21 PM1/24/03
to Austin_...@yahoo.com, Piers Cawley, perl6-l...@perl.org

There's also the fun of:

Dog bar(int);
Cat bar(int);

and

xyzzy(Dog);
xyzzy(Cat);

with the call of:

xyzzy(bar(1));

Just one of the many brain-benders that I'm glad Larry has to deal
with, not me. (Though this may be one of the reasons A6 is taking so
long...)

Nicholas Clark

unread,
Jan 24, 2003, 1:29:13 PM1/24/03
to Brent Dax, Dan Sugalski, Piers Cawley, perl6-l...@perl.org
On Fri, Jan 24, 2003 at 10:15:48AM -0800, Brent Dax wrote:
> Dan Sugalski:

> # Okay, I think I remembered the problem. Assume the following:
> #
> # list bar(int); # bar takes an int, returns a list
> # scalar bar(int); # bar takes an int, returns a scalar
> #
> # and also assume the following:
> #
> # xyzzy(scalar); # xyzzy takes a scalar
> # xyzzy(list); # xyzzy takes a list
> #
> # and then we make the call:
> #
> # xyzzy(bar(1));
> #
> # Which bar do we call? And which xyzzy?
>
> This is also a problem with using want().
>
> If we don't provide wants_scalar/wants_list, someone will build it with
> want(), so we might as well try to address it. I suggest that want()
> return a special value when the calling context is ambiguous, and any
> wants_scalar/wants_list property be designed to accommodate this
> (probably by specifying which one should be the default).

What? A junction of all the possible contexts valid here?

<ducks>

Nicholas Clark

Garrett Goebel

unread,
Jan 24, 2003, 1:27:47 PM1/24/03
to Brent Dax, Garrett Goebel, Dan Sugalski, Piers Cawley, perl6-l...@perl.org
From: Brent Dax [mailto:bren...@cpan.org]
> Garrett Goebel:
> # Brent Dax wrote:
> # >
> # > This is also a problem with using want().
> # >
> # > If we don't provide wants_scalar/wants_list, someone will
> # > build it with want(), so we might as well try to address
> # > it. I suggest that want() return a special value when
> # > the calling context is ambiguous, and any wants_scalar/
> # > wants_list property be designed to accommodate this
> # > (probably by specifying which one should be the default).
> #
> # Where "special value" is a junction: 'scalar' | 'list'?
>
> Actually, I was thinking C<undef>, though a junction of all
> the possible contexts might be good too. Remember, want()
> is more than just scalar/array now.

sure, sure...

I was ambiguously referring back to Dan's example, were xyzzy(scalar) and
xyzzy(list) were the only valid options.

--
Garrett Goebel
IS Development Specialist

ScriptPro Direct: 913.403.5261
5828 Reeds Road Main: 913.384.1008
Mission, KS 66202 Fax: 913.384.2180
www.scriptpro.com gar...@scriptpro.com

Brent Dax

unread,
Jan 24, 2003, 1:55:00 PM1/24/03
to Garrett Goebel, Dan Sugalski, Piers Cawley, perl6-l...@perl.org
Garrett Goebel:
# From: Brent Dax [mailto:bren...@cpan.org]
# > Actually, I was thinking C<undef>, though a junction of all
# > the possible contexts might be good too. Remember, want()
# > is more than just scalar/array now.
#
# sure, sure...
#
# I was ambiguously referring back to Dan's example, were
# xyzzy(scalar) and
# xyzzy(list) were the only valid options.

Ah. Then yes, that would be fine.

I suggest that we might require a special property to say "dispatch on
return value", which would give us a place to put in some information to
resolve conflicts.

Thomas A. Boyer

unread,
Jan 24, 2003, 1:54:54 PM1/24/03
to Dan Sugalski, Austin_...@yahoo.com, Piers Cawley, perl6-l...@perl.org

Dan Sugalski wrote:
> There's also the fun of:
>
> Dog bar(int);
> Cat bar(int);
>
> and
>
> xyzzy(Dog);
> xyzzy(Cat);
>
> with the call of:
>
> xyzzy(bar(1));
>
> Just one of the many brain-benders that I'm glad Larry has to deal
> with, not me. (Though this may be one of the reasons A6 is taking so
> long...)
> --

Ada handles this kind of problem. This is what used to be called operator overloading, before the phrase was coopted by C++ (before C++ came along, the limited version of operator overloading used in C++ was called *operand* overloading, since you're only allowed to overload based on operand types).

To disambiguate a call in the presence of full operator overloading, two full complete passes over the expression tree are required. The first pass is a bottom-up pass to collect all the potential return types; the second is a top-down pass that uses the context to eliminate some (hopefully all but one) of the available return types computed in the first pass. In Ada, if the second pass doesn't completely disambiguate the expression, it's considered an error.

I studied this stuff for my masters thesis, for which I added (Ada style) operator overloading to a Modula-2 compiler. When it was all over, I decided that I much prefer (C++ style) operand overloading. The computation to decide what the programmer meant is too complicated. For the user, not the compiler. Although the compiler can do it [the code is bulky, but not difficult to understand], I think that the programmer will be left in the dust. And I think that's a bad thing. In all but the simplest cases, the coder will have a very difficult time figuring out what the compiler's actually going to do.

As a matter of fact, I always thought that C<wantarray> was a nice compromise: let the programmer decide exactly what to do in the small number of cases where it's really useful.

So here's *my* vote against return-type multi-method disambiguation.

=thom
"Don't use that word [fantastic] to a lawyer; straining at gnats and swallowing camels is a required course in law school...." -- _Stranger_in_a_Strange_Land_

Austin Hastings

unread,
Jan 24, 2003, 2:27:03 PM1/24/03
to Brent Dax, Garrett Goebel, Dan Sugalski, Piers Cawley, perl6-l...@perl.org

--- Brent Dax <bren...@cpan.org> wrote:

> I suggest that we might require a special property to say "dispatch
> on return value", which would give us a place to put in some
> information to resolve conflicts.

In keeping with the notion of "a language for good programmers," I
think that the very act of defining two methods which are equivalent in
all but name is pretty much a deliberate statement of intent to
"dispatch on return value."

Perhaps an "is ambiguous" keyword to stuff the warning which we should,
in all fairness, emit for those who didn't actually mean what they
typed.

In the event that two modules export functions that collide, the
warning should prompt the user to add:

Dog bar($p is int) is ambiguous is default;

======
10 minutes and a visit to RFC-land later, I have some guy named after a
70's comedian writing:

http://dev.perl.org/rfc/256.html#Handling_dispatch_failure

However, experience indicates that sometimes the more specialized
variants of a multimethod are only provided as optimizations, and a
more general variant (in this case, the (Peg,Hole) variant) would
suffice as a default where such an ambiguity exists. It is proposed
that an additional parameterized attribute -- :default(ambiguous) -- be
provided so that one particular multimethod can be nominated as the
dispatch recipient in cases of ambiguity:


sub put_peg(Peg,Hole) : multi default(ambiguous) {
print "some kinda peg in some kinda hole\n"
}

Now, whenever a call to put_peg can't be dispatched because it's
ambiguous, this default variant will be called, rather than throwing an
exception.
======

Man, it gripes my wagger when he gets there first... :-/

Where two xyzzy functions could invoke different bar functions, the
list of bar() multis to invoke is as above, and the dispatch distance
is 1 in each case.

So either there is a C<bar(?) is default(ambiguous)> or there's an
exception.

Look, the water still beads!

=Austin


Murat Ünalan

unread,
Jan 24, 2003, 4:51:54 PM1/24/03
to du...@pobox.com, Austin Hastings, Dan Sugalski, Piers Cawley, perl6-l...@perl.org

> Strange. I think parameters to subroutines are in list
> context unless stated otherwise.
>
> -Scott

I agree. Do we miss something ?

Murat

0 new messages