Prototypes: the good, the bad,and the ugly

Arador on 2009-08-26T15:30:37

This is a reply to chromatic's post The Problem with Prototypes, but his blog didn't allow me to post it there so I post it here.

Pretty much everyone agrees that there are good (such as blocks and sometimes reference) prototypes and bad ones (scalar most of all). Few discuss the third class: the ugly glob prototype.

perlsub describes them as such:

A * allows the subroutine to accept a bareword, constant, scalar expression, typeglob, or a reference to a typeglob in that slot. The value will be available to the subroutine either as a simple scalar, or (in the latter two cases) as a reference to the typeglob.

In other words, they are the same as scalar prototypes, except that they also accept globs and barewords. This is mainly used to pass filehandles, like this:

sub foo (*) {...}

foo STDIN;

but in fact it can be used to pass any bareword to function, as it leaves the interpretation of it to the function.

It's tempting to call this bad, but it offers some API possibilities that would otherwise not be possible, hence I would call it ugly rather than bad per se.


Deliberately Unmentioned

chromatic on 2009-08-27T00:33:36

I didn't mention the glob prototype because I want to discourage the use of barewords.

Re:Deliberately Unmentioned

btilly on 2009-08-27T06:14:07

There is an omission in your list of good reasons to use prototypes.

A final good reason to use prototypes is in a comparison sub. If you pass sort a subroutine with ($$) as a prototype then it passes the arguments in @_ rather than setting $a and $b in the package that sort was called from. If you're setting up a sort in a different package than you're calling sort in, this can be a lifesaver.

This may seem like an obscure boundary case, but I've personally found it to be the most common reason why I've used prototypes at $work.