--- Michael Lazzaro <[EMAIL PROTECTED]> wrote: > > On Tuesday, March 11, 2003, at 11:19 AM, Austin Hastings wrote: > > But you can't wrap multi-ness, as far as I can tell. > > > > [A6] > > And it happens that the multimethod dispatch is smart enough to > find > > the ordinary single-invocant sysread method, even though it may not > > have been explicitly declared a multimethod. Multimethod dispatch > > happens to map directly onto ordinary method dispatch when there's > only > > one invocant. > > > > At least, that's how it works this week... > > [/A6] > > > > To me, this suggests that multithods can be bolted on top of > unithods. > > And presumably, likewise multisubs can be bolted atop Plain Old > Subs > > (POSs). > > I *think* that's just talking about the internal dispatch > mechanism... > e.g. the dispatcher treats one-invocant subs and multis the same way, > > and can map between them if necessary -- I don't think it's talking > about the semantic/syntactic rules for declaring them, just the guts > of > what happens when you eventually call one. > > So I still surmise it's a semantic error to override a C<sub> with a > C<multi>. (It doesn't have to be, internally, but otherwise I'm not > sure why you'd want a separate keyword C<multi> at all.) >
You want C<multi> to tell the compiler to build in multiple dispatch. Any invocation of C<foo> after C<multi foo> is going to be a penny dropped into the great Pachinko game of multimethod-dispatchery. By default, if no winning multi appears, the call falls out the bottom and winds up invoking the original sub(). > >> sub foo($a,$b,$c) {...} > >> > >> ... lots of code inbetween ... > >> > >> multi foo(int $a) {...} # ERROR - can't multi an existing > sub > >> multi foo(str $a) {...} > > In your example, where you have two separate modules that both have a > > C<foo>: > > > module CPANthing; > > sub foo($x) {...} > > > > module MyThing; > > sub foo($x) {...} # ERROR - redefined: multi won't, but "my" will > fix > > sub foo(int $x) {...} # ERROR - must use multi > > > > multi foo(int $x) {...} # OK > > multi foo($x: @a) {...} # OK > > multi foo($x: ?$y = 0) {...} # WARNING: compile-time or run-time? > > I would put the errors in different places, because there's nothing > wrong with having an identically named function in two different > namespaces, right? So I would rewrite that: > That's my bad. I should have made it more clear that I was moving the CPAN stuff into the same namespace, either via use CPANthing qw(foo); or by making them both *foo() for global. To wit: module CplusplusIO; sub *infix:<<(IOstream $io, Scalar $s) {...} module MyThing; sub *infix:<<(IOstream $io, Cat $c) {...} # I think this doesn't work multi *infix:<<(IOstream $io, Cat $c) {...} # Should work multi *infix:<<(IOstream $io, wchar_t $c) {...} # Woo-hoo! Next: STL My point is that if some CPAN author writes a cool module, and you use it and give over a piece of your namespace by importing the symbols, you should still be able to extend the CPAN module to the specific bits of your own data by bolting on multimethod that will make the invocation of the actual sub an acceptable thing. Further, since you don't necessarily KNOW going in that you're going to rework some or all of the interface, you don't want to try wrapping everything up: module CPANthing; sub foo(str $x) {...}; module MyThing; use CPANthing qw(foo(str $)); # Are siglets or psiglets going to be used for importing possibly # ambiguous symbols now? # ... my $a = "Hello, world!"; foo($a); # Okay so far, right? # But now you have some complex widget: my BigThingy $bt = init_big_thingy($a); foo($bt); # Except that $bt.tostr() yields debug info. So I really want a special # function that will do this for me: # Must be multi since I imported C<foo> multi foo(BigThingy $bt) { foo($bt.description); } # Now they both work: foo($a); # Calls sub CPANthing::foo() via local namespace due to import foo($bt); # Calls multi MyThing::foo() locally, which passes on ... =Austin