Tim Sweetman ti at
Mon Jan 15 21:56:36 GMT 2007

chromatic wrote:
> On Sunday 14 January 2007 15:01, Tim Sweetman wrote:
>>chromatic says (I paraphrase) if you implement AUTOLOAD, but don't
>>implement can, that's a bug, and you're lazy.

> It's lazy in the sense that leaving the gas on may save you having to turn it 
> on again ever, in the near future and in a permanent sense.

>>The UNIVERSAL perldoc also says:
>>>           "can" can be called as a class (static) method, an object
>>>method, or a function.

> Not the latest versions, which I patched [...]

>>[use] UNIVERSAL::can to push the
>>UNIVERSAL class's can implementation out of the way and do something
>>different (and hopefully better).

> That's not what the UNIVERSAL::can module does.

... That's exactly what it does!

"This module replaces UNIVERSAL::can() with a method that checks..."

> UNIVERSAL::can attempts to protect *working* code from breakage thanks to the 
> buggy code of other people

Evidently, the code it "protects" is not "working", otherwise you 
wouldn't need UNIVERSAL::can to "protect" it. It makes non-working code 
work, by replacing UNIVERSAL::can() with a method that does some other 

 > , warning copiously that invoking methods as
> functions has the nasty tendency to break working code.

> I suggest you immediately replace all of your constructors in your production 
> code with Acme::UNIVERSAL::new for a very quick lesson on the value of 
> adhering to superclass interfaces.  (If you don't use source control, 
> consider it two lessons.)

I completely understand that writing (for example)

   my $toast_rack = Toast::Rack->new;
   Toast::Rack::put_on_table ($toast_rack, $table);

is incorrect, exactly because any movement around the class hierarchy of 
put_on_table will cause the code to stop working.

As I see it, there are at least three schools of thought here:

1. Use AUTOLOAD. UNIVERSAL::can, ->can, and inheritance may then go 
wrong, but we don't care, because we're not using those, and 
UNIVERSAL::can isn't reliable anyway: it's POD says, you can't rely on 
can, because classes may use AUTOLOAD.

2. If you're using AUTOLOAD, you should redefine can, otherwise this is 
incorrect/lazy/inconsistent, but expecting UNIVERSAL::can to work as a 
function is incorrect and a bug (chromatic's view)

3. AUTOLOAD is a can of worms, and should be avoided wherever possible. 
You can work around its problems, but you'd end up with something like 
Class::Std's AUTOMETHOD, with reimplementation of UNIVERSAL::can and 
support for inheritance. (damian conway's view). (Class::Std does a 
similar trick, redefining UNIVERSAL::can).

 > adhering to superclass interfaces

UNIVERSAL's documentation is so vague on what you can expect from can 
that any fool (school of thought #1) can adhere to it.

(That's unless you decide that you don't like the superclass interface, 
and you're going to regard mere adherence to it as being a bug, and 
patch the definition of the superclass interface, which is what you did!)

I actually think option 1 is pretty crappy, because having a module 
which says it can't, but can, and once it does, admits it can, is just 
plain unhelpful. Eventually building AUTOMETHOD, or similar, into the 
language, and deprecating AUTOLOAD, would seem to be the way to go, if 
anyone cares enough to do it. Something like AUTOMETHOD means you can 
declare your autoloaded stuff once, and have can *and* invocation do the 
right thing. Expecting programmers to do something twice, when the 
effects of only doing it once are obscure and subtle, is not realistic. DRY.

> It seems reasonable to me to expect people writing OO Perl to have some vague 
> sense of how methods work.

You're expecting them to see a lurking problem over the horizon; a 
problem they may never have thought of, and which may never affect them. 
You're then expecting them to come to the same opinion as you (in 
contrast to the old version of the UNIVERSAL POD, or Damian Conway), and 
to code accordingly.


More information about the mailing list