A long time delayed, this weekend I finally implemented a solution to the can/AUTOLOAD issues that I thought up at Why breaking can() is acceptable. It is on CPAN as Class::AutoloadCAN.

Now I'm looking for feature suggestions, and ideas for good examples.

There are two feature possibilities that I have thought of.

The first is to provide an easy way to know within CAN what call-level you have to go to to get to the call that asked for the method. This would be useful if, for instance, someone wanted to implement a module that allowed for creating private or protected methods. The only problem is the API. I could set a global variable. But what do I call it? And if I export that then I can't use local to localize it.

The second is some version of NEXT. Of course the built-in SUPER or TheDamian's module won't work because they can only find the AUTOLOADs which are all pretty much the same. I need to have the logic in Class::AutoloadCAN. So I have to decide how to do it. The obvious way is to provide in the AUTOLOAD a "next" method. One question is how I should handle the "dreaded diamond". Do you avoid calling methods in the inherited superclass twice, or do I try to call methods in the inherited superclass twice?

There is a subtle conflict. It is nice that $obj->foo(@args); is always the same as $obj->can("foo")->(@args); but making that true with the next extension that I have proposed means breaking using $this->can("foo") == $that->can("foo") to test if two objects have the same method. I don't think that people would really mind if the latter broke, particularly considering what they get for it, but I'm not a heavy user of UNIVERSAL::can so I don't know how people like to use it. If you care either way then holler.

Now good example ideas. The most obvious one is to implement a class that allows you to do this:

private foo => sub { ... }; protected bar => sub { ... }; # The only reason for this is so that it can call on # private and protected versions of baz in a superclass, # and that requires the "next" functionality that I # thought of. (Guess how I realized that "next" might # be nice to have?) public baz => sub { ... };
Perhaps people would prefer the syntactic sugar of:
private foo { ... } protected bar { ... } public baz { ... }
even though it means using a source filter with the attendant fragility.

I think that people might want this because I've seen people complain of the lack of it in Perl, but I have no idea what a module that provides this should be called. Or what it further features it should have.

Feedback and further suggestions solicited.

Replies are listed 'Best First'.
Re: RFC: Class::AutoloadCAN
by dragonchild (Archbishop) on Apr 11, 2005 at 17:46 UTC
    My first thought is that you're fumbling towards multimethods. Pretty quickly, you're going to be implementing multimethods in PurePerl. Now, I'm not complaining about that idea, seeing as I think multimethods are the best feature of Perl6. But, I think you need to consider it as such when doing design work. If you do that, then you just look at the relevant sections of A12 and implement that. :-)

    even though it means using a source filter with the attendant fragility.

    No, it doesn't. It requires private 'foo' { ... };, using prototypes. The quotes around the method name is acceptable because base does the same thing.

    Update: Actually, you could just say private foo => { ... };. :-)

      My reaction to that thought is that there is no way that I am about to implement multi-methods. First of all doing so introduces complexities that I don't want to figure out. Secondly using multi-methods in a design introduces a level of complexity that I would like to avoid. (Note that I'm likely to be bad at designing something that I personally don't want to use.) Thirdly TheDamian already wrote Class::Multimethods and I've not heard complaints about what he did there.

      If there are complaints about Class::Multimethods and people really think that this module should go in the direction of multi-methods, then I'd be glad to give up maintainership to someone who wants to implement that chainsaw.

        Thirdly TheDamian already wrote Class::Multimethods and I've not heard complaints about what he did there.

        I think that's because no-one thinks of multimethods. :-) I seriously doubt that it's been used much, though it should because it solves a lot of problems.

        Now, the reason your module made me think of multimethods is that you're essentially defining multimethods, but from the opposite side. Where Class::MultiMethods allows you to define a series of targets and C::MM goes ahead and figures out what to do based on signatures, Class::AutoloadCAN allows you to specify at the class-level whether or not this class wants to do something about the request. By returning undef, you're indicating to the dispatcher that this is not the correct place for the given signature (which includes the method name).

        Personally, I think that the multimethod route is more maintainable, but that more people will reach for AutoloadCAN because it looks more like something they know. It's a screwdriver and not a tricorder to their hammer. :-)