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

A6: overloading multis on constness of parameters

12 views
Skip to first unread message

Joe Gottman

unread,
Mar 11, 2003, 9:01:21 PM3/11/03
to Perl6
Will it be possible in perl6 to overload multis on the const-ness of a
parameter, like C++ does? For instance,

multi getX(Foo $self:) returns Int {...} #const version
multi getX(Foo $self: is rw) returns Int is rw {...} #non-const version

If getX were called on a const Foo object then the first getX would be
called, and if it were called on a non-const Foo object the second one would
be.

Joe Gottman


Damian Conway

unread,
Mar 11, 2003, 9:35:08 PM3/11/03
to Perl6
Joe Gottman wrote:

> Will it be possible in perl6 to overload multis on the const-ness of a
> parameter, like C++ does? For instance,
>
> multi getX(Foo $self:) returns Int {...} #const version
> multi getX(Foo $self: is rw) returns Int is rw {...} #non-const version

That second one would have to be:

multi getX(Foo $self is rw:) returns Int is rw {...}


Then we have the issue that Perl 6 objects can't really be "constant",
since C<is constant> is a compile-time trait of *containers*...really just
a "don't assign to this container" marker.

However, within those limitations, I guess it's possible. After all, we have
to check for lvaluability of C<is rw> parameters anyway.

Damian

Larry Wall

unread,
Mar 12, 2003, 1:20:24 PM3/12/03
to Perl6

Might be one of those things that is taken as a tie-breaker, all other
things being equal. I'm thinking return types fall into the same category.

Larry

Piers Cawley

unread,
Mar 12, 2003, 7:15:42 PM3/12/03
to Joe Gottman, Perl6
"Joe Gottman" <jgot...@carolina.rr.com> writes:

Speaking of multis and constants, Greg McCarroll wondered on IRC if
this would work:

multi factorial (Int 0) { 1 }
multi factorial (Int $n) { $n * factorial($n-1) }

Disregarding the fact that you should really write that as:


sub factorial (Int $n) {
my multi tail_fac ($result, 0) { $result }
my multi tail_fac ($result, $n) { tail_fac( $result * $n, $n - 1 ) }
tail_fac(1, $n);
}

(Assuming you want to do it recursively that is...)


--
Piers

Joe Gottman

unread,
Mar 12, 2003, 10:51:39 PM3/12/03
to Perl6

How would I take a get a reference to the second one? I assume I could
get a reference to the first by

$ref = &getX(Foo);

Joe Gottman


Luke Palmer

unread,
Mar 12, 2003, 11:03:36 PM3/12/03
to jgot...@carolina.rr.com, perl6-l...@perl.org

Well, if there's overloading based on traits, siglets must support
traits. So, it would have to be:

$ref = &getX(Foo is rw:);

(The first would be)

$ref = &getX(Foo:);

Backwhacking those couldn't hurt, either.

Luke

Damian Conway

unread,
Mar 13, 2003, 9:15:19 PM3/13/03
to Piers Cawley, perl6-l...@perl.org
Piers Cawley wrote:

> Speaking of multis and constants, Greg McCarroll wondered on IRC if
> this would work:
>
> multi factorial (Int 0) { 1 }
> multi factorial (Int $n) { $n * factorial($n-1) }

Probably not. We did discuss whether multimethods should be able to be
overloaded by value, but concluded (for that week, at least ;-) that this
might prove syntactically excessive.

Besides which, since multimethod dispatch will have to use C<isa> to determine
type compatibility on parameters anyway, it's trivial to implement this form
of value-based dispatch yourself:

class Zero {
multi *isa ($obj, Zero $class) { $obj ~~ 0 }
}

# and then...

multi factorial (Int&Zero $g) { 1 }

or, supposing we have some form of parameterized types, you could create
something more generic like:

class Val($N) {
multi *isa ($obj, Val($N) $class) { $obj ~~ $N }
}

# and then...

multi factorial (Int&Val(0) $g) { 1 }


;-)

Damian

Luke Palmer

unread,
Mar 13, 2003, 9:24:20 PM3/13/03
to dam...@conway.org, pdca...@bofh.org.uk, perl6-l...@perl.org
> or, supposing we have some form of parameterized types, you could create
> something more generic like:
>
> class Val($N) {
> multi *isa ($obj, Val($N) $class) { $obj ~~ $N }
> }
>
> # and then...
>
> multi factorial (Int&Val(0) $g) { 1 }

Yes, YES! Marvelous!

Not that that couldn't be done with a closure anyway...

{
my Class %valClasses;

sub Val($N) returns Class {
my Class $rclass = %valClasses{$N} //= class {
multi *isa ($obj, $rclass $class) { $obj ~~ $N }
}
}
}

multi factorial (Int & Val(0) $g) { 1 }

Hmm, would Val(0) be evaluated at compile-time in that case... or must
I mark it with some sort of trait, or do some other kind of trick.

Cool, anyhow.

Luke

Damian Conway

unread,
Mar 13, 2003, 9:45:56 PM3/13/03
to perl6-l...@perl.org
Luke Palmer wrote:

> Not that that couldn't be done with a closure anyway...
>
> {
> my Class %valClasses;
>
> sub Val($N) returns Class {
> my Class $rclass = %valClasses{$N} //= class {
> multi *isa ($obj, $rclass $class) { $obj ~~ $N }
> }
> }
> }
>
> multi factorial (Int & Val(0) $g) { 1 }

I don't think so. I seriously doubt you can put a run-time-evaluated sub call
in a type specification <visions of Dan fainting in horror> ;-)
A C<macro> might do the trick though.

Oh, and I was wrong to originally write: C<multi *isa ...>
Multimethods live in their own namespace. No * required.

Damian

Dan Sugalski

unread,
Mar 14, 2003, 10:57:19 AM3/14/03
to Damian Conway, perl6-l...@perl.org
At 1:45 PM +1100 3/14/03, Damian Conway wrote:
>Luke Palmer wrote:
>
>>Not that that couldn't be done with a closure anyway...
>>
>> {
>> my Class %valClasses;
>>
>> sub Val($N) returns Class {
>> my Class $rclass = %valClasses{$N} //= class {
>> multi *isa ($obj, $rclass $class) { $obj ~~ $N }
>> } }
>> }
>>
>> multi factorial (Int & Val(0) $g) { 1 }
>
>I don't think so. I seriously doubt you can put a run-time-evaluated
>sub call in a type specification <visions of Dan fainting in horror>
>;-)
>A C<macro> might do the trick though.

Hey, I'm perfectly happy to delegate the entirety of sub dispatch to
someone else's code. That's fine with me. ;-P
--
Dan

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

Larry Wall

unread,
Mar 14, 2003, 12:29:09 PM3/14/03
to perl6-l...@perl.org
On Fri, Mar 14, 2003 at 01:45:56PM +1100, Damian Conway wrote:
: Oh, and I was wrong to originally write: C<multi *isa ...>

Sorry, you're not even wrong. :-)

: Multimethods live in their own namespace. No * required.

Alternately, we require the C<*> in order to accurately document
their scope. And I do think they live in C<*>. Otherwise we need to
come up with yet another name for the global scope that happens to
contain multimethods. An argument can also be made that we should
do that anyway on the grounds that we might someday have scoped
multi-methods of some kind or other.

I suppose can allow a C<sub *> in the same scope as C<multi *> for
the case that you want a global override of all the multimethods.
It just looks for the sub first. If that sub then wants to redispatch
to the multimethods, it'd have to use some special multimethod syntax
that doesn't look like a sub invocation, such as the notional

($a,$b,$c) forwhich foo()

we talked about in Sebastopol, however we end up spelling "forwhich".
It's really a kind of postpositional topicalizer for the following
predicate. English doesn't really have any good ones of those.
If I were Japanese, I'd spell it "wa" or "ga" or "no".

Well, okay, I'd actually spell it "は" or "が" or "の" if I were
*really* Japanese. :-)

Larry

Austin Hastings

unread,
Mar 14, 2003, 3:53:47 PM3/14/03
to perl6-l...@perl.org
In the tradition of Mr. Lazzaro, a chart:

For origin of the AUTOLOAD/DISPATCH stuff, see:
http://groups.google.com/groups?hl=en&selm=3E6E853D.9090604%40conway.org

Does this make sense as far as the "Rules of Dispatch”? I’ve included a
few suggestions where capability or sequence was unclear.

Given:

package pkg;
use Xclass qw(foo);
my $x = returns_an_Xclass();

foo $x; # Function-style
$x.foo; # Method-style
foo $x:; # Invocant-style (Is the colon needed?)


The dispatcher looks for:

(FM = Function-style or Method/Invocant-style, only)

##| FM Declaration Note
==+===========================================================

A1| my macro foo
A2| macro pkg::foo See note 0, below
A3| macro *foo

B-| Only for method, invocant styles.
B1| M submethod Xclass::DISPATCH May be at runtime
B2| M method Xclass::DISPATCH “
B3| M method SUPER::DISPATCH “ (SUPER meaning inherited)

C1| my sub DISPATCH
C2| sub pkg::DISPATCH
C3| sub *DISPATCH

D1| multi DISPATCH What's the signature required?

E1| my submethod foo Does this make sense?
E2| submethod pkg::foo Or this?
E3| submethod Xclass::foo Only method, invocant styles.
E4| submethod *foo See note 1, below.

F1| M my method|rule Xclass::foo See note 2, below.
F2| M my method|rule foo See note 2, below.
F3| M method|rule Xclass::foo
F4| M method|rule SUPER::foo (SUPER meaning inherited)
F5| M method|rule *foo See note 3, below.

G1| F my sub &foo See note 4, below.
G2| F sub pkg::foo
G3| F sub *foo

H1| my multi &foo See note 5.
H2| multi pkg::foo See note 5.
H3| multi *foo Requires compatible signature.

I1| M my submethod Xclass::AUTOLOAD
I2| M my method|rule Xclass::AUTOLOAD
I3| M submethod Xclass::AUTOLOAD
I4| M method Xclass::AUTOLOAD

J1| F? my sub AUTOLOAD
J2| F? sub pkg::AUTOLOAD
J3| F? sub *AUTOLOAD

K1| F? my multi AUTOLOAD See note 5.
K2| F? multi pkg::AUTOLOAD See note 5.
K3| F? multi *AUTOLOAD Requires compatible signature.

NOTES
=====

Note 0: macro pkg::foo -- There's no forward declaring macros, because
of the need to modify the behavior of the parser. But can macros be
package scoped? I assume yes, because the act of doing "use pkg;"
causes pkg to maybe get parsed, and if pkg defines macro foo, then
macro foo pollutes the namespace of the user if it doesn't have package
scope. From this, I assume that leaving and re-entering the package
scope should reactivate the macro. Is this also true?

pkg p1;
macro foo ...

pkg p2;
foo; # Doesn't invoke macro

pkg p1;
foo; # Invokes macro.

Note 1: submethod *foo -- Submethods are a little weird, since the
intent is (from A6) a non-inheritable method. Defining C<submethod
*foo> sort of implies defining a non-inheritable method for all objects
(which makes it essentially inherited, although things like SUPER won't
invoke it). This seems like the sort of bizarre, hideously dangerous
thing that was common in p4/5. Is it desired/supported? (I can think of
no use for it.)

Note 2: my method foo -- This is essentially "method with lexical
scope", which boggles my mind. But then it occurred to me that in the
right context (e.g. C<class X { my method foo()...}> this might be the
way to do submethods. Is it? Alternatively, is saying C<my method
Xclass::foo> a legal way to wrench control from the Xclass?

Note 3: method *foo -- This is speculation. A6 says, "Methods and
submethods are ordinarily package scoped". So I'm inclined to wonder
about extraordinary methods. Is this another useless cul-de-sac, or
does the design team have something concrete in mind here?

Note 4: subs named "foo", regardless of signature -- My interpretation
of subs is that there's no multidispatch once the name is matched.
Thus, if a sub with no signature exists in scope, it catches all calls
to that name. While if a sub with a signature exists in scope, it
catches calls to that name with matching signature. Some of Damian's
posts have seemed to me to imply that calls that don't match the
signature of the sub will FAIL, rather than dispatch on multimethods.
This needs clarification.

Note 5: my multi &foo -- Another clarification is needed. A6 says, 'You
can declare "scoped" subroutines by explicitly putting a my or our on
the front of the declaration'. The implication of the following
examples is of C<sub> declarations, strengthened by the explicit
mention of defining scoped macros using C<my>. But, in the interest of
being a pain in the neck, I figured I should request clarification: Can
I define a scoped multi? If so, how? If not, why not? (The "if not" is
somewhat important, given that a huge number of built-ins are going to
become multis. If I can't scope them, how about C<.wrap>ing them? Will
wrappers be scoped?)


Trey Harris

unread,
Mar 15, 2003, 11:39:22 PM3/15/03
to Luke Palmer, dam...@conway.org, pdca...@bofh.org.uk, perl6-l...@perl.org
In a message dated Thu, 13 Mar 2003, Luke Palmer writes:
> {
> my Class %valClasses;
>
> sub Val($N) returns Class {
> my Class $rclass = %valClasses{$N} //= class {
> multi *isa ($obj, $rclass $class) { $obj ~~ $N }
> }
> }
> }
>
> multi factorial (Int & Val(0) $g) { 1 }

Isn't this exactly what C<is cached> is for?

sub Val($N) is cached returns Class {


class {
multi *isa ($obj, $rclass $class) { $obj ~~ $N }
}
}

multi factorial (Int & Val(0) $g) { 1 }

(This is ignoring the fact that you can't use a runtime-evaluated sub in a
type declaration so the multi declaration wouldn't actually work.)

--
Trey Harris
Vice President
SAGE -- The System Administrators Guild (www.sage.org)
Opinions above are not necessarily those of SAGE.

0 new messages