http://qs1969.pair.com?node_id=342840


in reply to Re: Re: Why breaking can() is acceptable
in thread Why breaking can() is acceptable

I never said it would be easy, I just said that you shouldn't break can for the sake of AUTOLOAD. But I am not a big fan of AUTOLOAD, while I do make (occasional) use of can so I would sooner throw away AUTOLOAD before I gave up can.

I will take you up on your challange, but with one change. I ask that you post and interesting example of AUTOLOAD, for which I will write a version of can. Partially because I don't like or use AUTOLOAD very much and to be honest would have a hard time coming up with an interesting example, and partially because I am not a fan of writing vaguely specified code for others to shoot holes into. Something like this is clearly complex, I do not deny that, but if you have a solid and well thought out implementation of AUTOLOAD I expect it would be possible to write a version of can to go with it.

-stvn

Replies are listed 'Best First'.
Re: Re: Re: Re: Why breaking can() is acceptable
by tilly (Archbishop) on Apr 06, 2004 at 06:20 UTC
    Larry Wall's original intention is shown pretty well by Shell. You could choose to pick on various other core modules that use AUTOLOAD.

    Some nodes where I have used AUTOLOAD include Class::FlyweightWrapper, Re (tilly) 1: Nested Classes and the poorly implemented Re (tilly) 1: Reverse Inheritance Irritance.

    Note that when I've chosen to use AUTOLOAD in the past, it tends to be short. A doable solution which takes considerable overhead to implement is going to underscore my point that, as Perl is currently structured, using AUTOLOAD and can together runs into trouble.

      Shell is a perfect example of how AUTOLOAD should be used. And looking over it, I cannot see a good way to write can for it since it really just executes on the shell anything you give it (whoa security risk!). However if you specified your available shell commands, then you could make a reasonable can with no trouble at all. Even Larry seemed to think maybe they were playing with fire (quoted from here)

      That's maybe too gonzo. It actually exports an AUTOLOAD to the current package (and uncovered a bug in Beta 3, by the way). Maybe the usual usage should be
      use Shell qw(echo cat ps cp);
      Larry
      If we were to follow Larry's suggestion, the implementation of can becomes very simple to implement as we know what methods/functions are being created/AUTOLOADed.
      Note that when I've chosen to use AUTOLOAD in the past, it tends to be short.
      I have used AUTOLOAD on occasion too, but only when I really need to (and just as with you) it tends to be short. An example is in Class::Trait here. I am not sure if my usage breaks can, but you can be sure I will test it in the next release.

      As for Class::FlyweightWrapper, here is your can

      Regarding Re (tilly) 1: Nested Classes, a can like addition to your object system is easily enough to implement since you have all the methods defined in a hash already. As this is an example of creating your own object system, I wont bother trying to think of how a version of can might fair in other situations (inheritance, multiple-inheritance, etc), since creating your own object system is hairy enough, and your implementation is incomplete.

      As for Re (tilly) 1: Reverse Inheritance Irritance, you are just dispatching your calls to the parent object, so it makes sense you can dispatch requests to can as well. Like I said, it may not be easy, but I think in many cases it is worth it, you may not agree with that, and that is your choice.

      -stvn
        Feedback.

        On Class::Trait. Not a bug, but anyone mixing SUPER:: and multiple inheritance is simply asking for problems. If you want to support multiple inheritance, then you would do well to look at whether you are called from NEXT:: as well. (I'm actually not sure what Class::Trait is supposed to be for, but that is a different issue.) I'm also amused that you apparently find it more acceptable for a module author to say, "I won't support multiple inheritance," than "I won't support can()."

        On Class::FlyweightWrapper, the subroutine that you return is the one that is meant to be given the private object, not the public one. Since the caller isn't supposed to have the private object, that should be useless. Furthermore the reason why you can't inherit is because the implementation (including inheritance) is supposed to be done in the private hierarchy with public hooks defined where you decide.

        About Nested Classes, I'd prefer to say that the system is basic rather than incomplete. It does what it claims to do. That thing is useful as it stands. Opinions on what belongs in an object system vary widely, so you're never going to have everything that everyone thinks should be there (unless you've implemented stuff that a lot of people think shouldn't be there as well).

        On the Reverse Inheritance Irritance, if I override can() there and call SUPER::can() first (to handle the case where I have implemented the method elsewhere), then if a parent class has overridden can() for their AUTOLOAD, can will return the parent's AUTOLOAD, while calling the method is going to call my AUTOLOAD. The truth value of can() is right, but the subroutine returned is wrong. Calling UNIVERSAL::can alleviates the problem somewhat, unless someone has overridden UNIVERSAL::can. (Possibly because they want to follow the scheme that I had in the root node which makes AUTOLOAD and multiple inheritance able to cooperate seamlessly.)