Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Class::Multimethods namespace collusion

by bakunin (Scribe)
on Feb 16, 2004 at 16:45 UTC ( #329362=perlquestion: print w/ replies, xml ) Need Help??
bakunin has asked for the wisdom of the Perl Monks concerning the following question:

Hello all!

Yesterday, I decided to use Class::Multimethods to overload my class methods which have endlessly changing argument lists.
As usual, I got my hands dirty right away without carefully reading the excellent tutorial. A surprise, with full of spite, was awaiting:
## in file Foo.pm: package Foo; use strict; use Class::Multimethods; multimethod new => ('$') => sub { print "I'm the constructor for Foo\n"; bless {},$_[0]; }; 1; ##in file Foo2.pm: package Foo2; use strict; use Class::Multimethods; multimethod new => ('$') => sub { print "I'm the constructor for Foo2\n"; bless {},$_[0]; }; 1; ## in main.pl: package main; use strict; use Foo; use Foo2; Foo->new(); Foo2->new(); ## ==== OUTPUT ==== ## #I'm the constructor for Foo2 #I'm the constructor for Foo2

When I read the tutorial, this line caught my eye:

"...all multimethod variants share a common namespace that is independent of their individual package namespaces."

Meaning, do not use different class constructors with the same name!!
Well, I came up with the following, but again as usual I want to ask the other monks before putting it into the assembly line:
package Foo; use strict; use Class::Multimethods; *Foo::new = \&_newFoo; multimethod _newFoo => ('$') => sub { print "I'm constructor for Foo\n"; bless {},$_[0]; }; 1; ## Foo.2pm package Foo2; use strict; use Class::Multimethods; *Foo2::new = \&_newFoo2; multimethod _newFoo2 => ('$') => sub { print "I'm constructor for Foo2\n"; bless {},$_[0]; }; 1; ## Now, it works as it should be. Of course with also other ## overloaded methods like _newFoo('$','HASH'),_newFoo2('$','$')
Here are my questions: Am I missing something in Multimethods?
If not, is my method useful? Any side effects that you might think of, esp. with inheritance? How would you solve this?

Thanks !!

Comment on Class::Multimethods namespace collusion
Select or Download Code
Re: Class::Multimethods namespace collusion
by adrianh (Chancellor) on Feb 16, 2004 at 23:45 UTC
    How would you solve this?

    Not have the object constructor as a multi-method?

    Can you explain in more detail what the problem that you're trying to solve by having new() as a multi-method is? It's not clear from your example.

      Thanks for replying. Let me try to paraphrase:

      ## FOR ILLUSTRATION PURPOSES, code below will not run!! use strict; use SWFAuto::Button; use SWFAuto::Text; my $buttonA = SWFAuto::Button->new(); my $buttonB = SWFAuto::Button->new("I'm a button"); my $textA = SWFAuto::Text->new(); my $textB = SWFAuto::Text->new("I'm a text"); ## SWFAuto::Text::new is called 4 times!

      Basically this is the usage of the modules. The constructor "new" is overloaded in both classes. And, both have the same argument lists. And then whichever you "use Module;" last, its constructor gets called.

      Well, at least the typeglob came very handy this time for me!
Re: Class::Multimethods namespace collusion
by TheDamian (Priest) on Feb 17, 2004 at 23:22 UTC

    The correct solution to this problem is to enhance Class::Multimethods to handle it correctly. ;-)

    The problem boils down to the fact that the first argument passed to any Perl 5 constructor is the name of the class on which the constructor was called.

    So, in effect, every constructor multimethod has to have '$' as the type specifier for its first parameter. Which leaves no way to tell them apart.

    But there's no reason that a multiple dispatch system has to restrict itself to considering just the types of the arguments on which it's dispatching. An obvious extension is to allow the dispatcher to examine the values of those parameters and differentiate on that basis too.

    Suppose, for example, that we were to generalize Class::Multimethods so that parameters could also be specified as a subroutine. When such a variant was considered in the dispatch process, instead of working out the inheritance distance from the argument's class to the parameter class, Class::Multimethods would pass the argument to the subroutine, and use the sub's return value as the distance (with undef indicating type incompatibility).

    Then one could set up subroutine generators for just about any kind of dispatch criterion. For example:

    sub Value_eq { my ($target_value) = @_; sub { $_[0] eq $target_value ? 0 : undef } } sub Negative { sub { $_[0] < 0 ? 0 : undef } }

    Then we would be able to code class constructors as multimethods, like so:

    package Base; multimethod new => (Value_eq('Base')) => sub {...} multimethod new => (Value_eq('Base'), Negative) => sub {...} multimethod new => (Value_eq('Base'), '#') => sub {...} package Der; use base 'Base'; multimethod new => (Value_eq('Der')) => sub {...} multimethod new => (Value_eq('Der'), '$') => sub {...} # etc.

    Of course, we could simplify that even further by providing a subroutine generator that specifically compared argument values against the name of the current class:

    sub This::Class { my $target_value = caller; sub { $_[0] eq $target_value ? 0 : undef } }

    With which we could code multiply dispatched constructors like so:

    package Base; multimethod new => (This::Class) => sub {...} multimethod new => (This::Class, Negative) => sub {...} multimethod new => (This::Class, '#') => sub {...} package Der; use base 'Base'; multimethod new => (This::Class) => sub {...} multimethod new => (This::Class, '$') => sub {...} # etc.

    Now, if only I had the tuits to actually make Class::Multimethods work that way! :-(

    Ah well...at least I can put it at the top of the module's ToDo list.

    Damian

      Thank you very much!! I hope this node will be very enlightening for those who use Class::Multimethods.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://329362]
Approved by TStanley
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (13)
As of 2014-09-19 12:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (137 votes), past polls