Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Re: Re: Why breaking can() is acceptable

by tilly (Archbishop)
on Apr 06, 2004 at 05:10 UTC ( #342836=note: print w/replies, xml ) Need Help??

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

I believe that getting a replacement can method to work absolutely correctly in all situations is far harder than it looks. I tried to explain some (not all!) of the issues in my root node. If you think that it is easier than I do, then post an interesting example of an AUTOLOAD and how you'd override can, and I'll try to demonstrate how - by your standards - your code is incomplete.

If the task proves difficult for you, right after you just read a description of some of the things that can go wrong, can we both agree that expecting people to consistently get it right is unrealistic?

  • Comment on Re: Re: Why breaking can() is acceptable

Replies are listed 'Best First'.
Re: Re: Re: Why breaking can() is acceptable
by stvn (Monsignor) on Apr 06, 2004 at 05:32 UTC

    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.

      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);
        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.

Re: Re: Re: Why breaking can() is acceptable
by dragonchild (Archbishop) on Apr 06, 2004 at 11:59 UTC
    The following snippet is taken from that example I alluded to above.
    # This exists to provide object-specific can() functionality. # 1) If this is an object, check to see if the method is an element na +me. # 2) If either is not true, redispatch to the parent's can() method. + sub can { ( ref($_[0]) && UNIVERSAL::isa( $_[0]->elements, 'HASH' ) && exists $_[0]->elements->{$_[1]} ) || ( $_[0]->SUPER::can($_[1]) ); } sub AUTOLOAD { (my $name = our $AUTOLOAD) =~ s/.*::([^:]+)$/$1/; my $self = shift; unless ($name eq lc $name || exists $self->element_classes->{lc $n +ame}) { return eval "$self->SUPER::$meth(@_);"; } $self->elements->{$name} = shift if @_; $self->elements->{$name}; }

    A few notes:

    1. This is a container object, providing a unified interface to parsing stuff. It acts as a record and the elements are the various columns. Each record may have different columns and the goal was to provide a way of allowing the user to call the column name as a method and get the column object.
    2. element_classes is a method which returns a hashref of name-class pairs. The name is the name of the column as provided to this object in the constructor. The class is the class of the column.
    3. elements is a hashref which actually contains the column objects in name-object pairs. It is guaranteed that the names from element_classes() will be identical to the names from elements().

    This implementation has the added benefit of the fact that it's currently working in production. Now, nothing inherits from it (yet) and I do not use MI in production code, for the reasons well-cited elsewhere.

    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://342836]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (5)
As of 2023-03-24 04:05 GMT
Find Nodes?
    Voting Booth?
    Which type of climate do you prefer to live in?

    Results (60 votes). Check out past polls.