Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

Re: Why breaking can() is acceptable

by Beechbone (Friar)
on Apr 06, 2004 at 08:21 UTC ( #342862=note: print w/replies, xml ) Need Help??

in reply to Why breaking can() is acceptable

I think this discussion is pointless. You either provide an interface to your module---then you decide if it supports can()---or you implement an interface another module expects---then the author of that module decided if can() is needed. That's it.

Implementing a working can() isn't that hard. I'd say this should work (ATTN: untested, WILL contain syntax errors):

sub can { my ($self, $what, $code) = (@_[0,1], undef); return $code if $code = $self->UNIVERSAL::can($what); return $code if $code = $self->_can($what); foreach my $superclass (@ISA) { return $code if $code = eval "\$self->${superclass}::can(\$wha +t)"; } return undef; } sub _can { # aka _load() my ($self, $what) = @_; if ($what eq 'foo') { return sub {'foo'}; } else { return undef; } } sub AUTOLOAD { my ($self, $code) = ($_[0], undef); goto &$code if $code = $self->can($AUTOLOAD); die "oops"; }
PS: This even provides a working way for using AUTOLOAD with multi-inheritance, I'd say.

Search, Ask, Know

Replies are listed 'Best First'.
Re: Re: Why breaking can() is acceptable
by tilly (Archbishop) on Apr 06, 2004 at 15:42 UTC
    If everyone had your attitude, then I wouldn't have seen a point in having the discussion either. The issue is that there are people who think that any module which decides that can() shall not be supported is broken. Since you apparently agree with me that breaking can() is OK, we would have had little to discuss.

    As for the solution that you provided, it tries to do a good job, but still has several subtle issues with it. First of all, and glaringly, your $AUTOLOAD always includes the package name and so will fail to do any kind of inheritance. That can (and should) be readily fixed. Secondly your AUTOLOAD fails (uninformatively) if you accidentally call an unimplemented function procedurally in any class that inherits from it. Thirdly if you appear partway up the class hierarchy in a multiple inheritance scheme, you will implicitly prune the class hierarchy for AUTOLOADed stuff to that hierarchy, contrary to what you claim about it being a working way for using AUTOLOAD with multiple inheritance. That is a common AUTOLOAD problem, your can matches what your AUTOLOAD does. (And it is a common multiple inheritance problem, people tend to think about the cases where they are at the bottom or top of the hierarchy, and don't think through being in the middle of the inheritance tree.) And finally it is worth noting that anyone who tries to do what I suggested with a UNIVERSAL::AUTOLOAD to allow can() and AUTOLOAD to play together will find that things implemented with their AUTOLOAD override yours. (Ironically this is probably a good thing.)

Log In?

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

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

    Results (60 votes). Check out past polls.