views:

59

answers:

3

In the linked SO answer, Eric illustrates a way to call a subroutine, which accepts arrays by reference as arguments, and use the prototypes to allow the caller code to pass the array names without using reference operator \@; the way built-ins like push @array, $value do.

# Original code:
sub Hello { my ($x_ref, $y_ref) = @_; ...}
Hello(\@x, \@y);

# Same thing using array ref prototype:
sub Hello (\@\@$) {...}
Hello(@x, @y);

My question is, is this considered to be a Best Practice? And what are the guidelines on the pattern's use?

It seems like this pattern should either be used ONLY for built-ins, or for 100% of subroutines that accept array arguments in all of your code.

Otherwise code maintenance and use of your subs becomes fragile since the developer never knows whether a particular sub, when called, should be forced to reference an array or not.

An additional point of fragility is that you become confused between doing such calls and legitimately using two arrays combined into one using a comma operator.

On the positive side, using the pattern prevents the "forgot to reference the array" bugs, and makes the code calling the subroutines somewhat more readable.

P.S. I don't have Conway's book handy and don't recall if he ever discussed the topic, to pre-empt RTFB responses.

+2  A: 

Let's ask Perl::Critic:

echo "use strict; sub Hello (\@\@$) {...}" | perlcritic
Subroutine prototypes used at line 1, column 1.  See page 194 of PBP.  (Severity: 5)

Yeah, that would be a no.

Chas. Owens
@Chas - Thanks! Didn't think of that! I should probably be ashamed but I never used Perl::Critic. Wonder how my average code scores - since I rarely disagree with Conway's main ideas I hope not too badly :)
DVK
I think the general warning about prototypes from PBP is that they are commonly used by beginners as argument validation. PBP doesn't seem to consider their proper use. Obviously the Perl core considers prototypes useful enough to have them on nearly every builtin.
Eric Strom
@Eric Storm And it is generally agreed that prototypes on the built-in functions was a mistake, but nothing can be done about it now (due to backwards compatibility issues).
Chas. Owens
-1: In the absence of supporting reasons, "PBP doesn't like it" is not a valid argument. IIRC, PBP itself even says something to the effect of "don't blindly follow my advice, read my reasons and make your own decision."
Dave Sherohman
@Dave Sherohman I am sorry, I thought the reasons prototypes were dangerous and should not be used without very good reasons were well known and widely written about. You can start with [FMTEYEWKPP](http://www.perlmonks.org/?node_id=861966).
Chas. Owens
Removing the downvote now that you've provided a link to (a most excellent) source of information to substantiate the answer. The reasons may be well-known, but the OP apparently didn't know them (since he asked the question).
Dave Sherohman
...or not removed. SO has declared my downvote "locked in unless this answer is edited." When did that misfeature get added?
Dave Sherohman
+4  A: 

Only use prototypes when you're trying to extend Perl's syntax: e.g. if you're building Moose, or something like the examples in Dominus' Higher Order Perl. If you're doing that, you know enough to disregard PBP (and to annotate your code to shut Perl::Critic up). If you're doing anything else, don't use them.

Michael Carman
A: 

I tend to think that anything that makes a subroutine act differently than any other subroutine isn't the best thing. There might be instances where it's a good idea, but in general it's more special cases, documentation, and other things to remember. The more your code acts like most other Perl code, the easier you make things for your users.

Notice that this isn't the main complaint that Perl Best Practices has with prototypes, which is an ugly kludge in Perl.

brian d foy