This is the mail archive of the
automake@gnu.org
mailing list for the automake project.
Re: automake and 'strict' Perl5
Rodolphe Ortalo <Rodolphe.Ortalo@cert.fr> writes:
> All the points you raise are generally true. Furthermore, as a Perl
> programmer, I usually tend to agree with everyone. ;-)
TMTOWTDI. :)
> There is a check on the number of arguments when prototypes are provided
> and 'use strict;' is enabled. And also a basic check on parms type
> (scalar, list). This is mainly why I introduced them. It was mainly for
> me, to help me maintain the integrity of the overall program while doing
> these modifications everywhere. [Of course, I accidentally erased a
> parameter somewhere at some point (especially during the last part of
> the night) and the prototype hints found that typos. That was useful.
> Really.]
> I don't know if these prototypes can have real bad side-effects (in
> fact, even though I'm aware of such potentially ill behavior, I've never
> observed it in real-life scripts). I tend to view them as a kind of
> comment, that happens to be understood by the perl interpreter -
> something that it sometimes confess to the user.
Prototypes in Perl are a double-edged sword.
First off, there's a backwards-compat issue; I believe prototypes were
only introduced in 5.002 and had some bugs up until 5.004. I'm not sure
what version of Perl this is being targetted at.
Second, while prototypes certainly can do all of the neat things that you
mention above, Perl prototypes are very deceptive from the perspective of
a C programmer. Perl prototypes can *change the semantic meaning* of
expressions; they're not just aids to the compiler/interpretor to help it
find bugs.
The most prominant example is something like this: Suppose you have a
function that takes two arguments, adds them together, and returns the
result. Something like:
sub sum { my ($a, $b) = @_; return $a + $b }
as in:
va:~> perl
sub sum { my ($a, $b) = @_; return $a + $b }
print sum (1, 2), "\n";
3
So far so good. Perl doesn't care where it gets those arguments from, so
you can also do:
va:~> perl
sub sum { my ($a, $b) = @_; return $a + $b }
@a = (1, 2);
print sum (@a), "\n";
3
This is occasionally very convenient. But watch this:
va:~> perl
sub sum ($$) { my ($a, $b) = @_; return $a + $b }
@a = (1, 2);
print sum (@a), "\n";
Not enough arguments for main::sum at - line 3, near "@a)"
Execution of - aborted due to compilation errors.
Using prototypes breaks that idiom. Prototypes are *strict*. If you say
the sub takes two scalars, you have to then pass it two scalars, and if
you try to pass it anything else, it dies.
Here's something more subtle:
va:~> perl
sub sum { my ($a, $b) = @_; return $a + $b }
@a = (1, 2);
print sum (@a, 3), "\n"
3
Now this is clearly a bug. You're actually passing a sub that takes two
arguments an array and a number, and it's correctly (according to how you
wrote it) taking the first two and adding them and ignoring the third. It
might be nice for prototypes to fix this. But look at what they actually
do:
va:~> perl
sub sum ($$) { my ($a, $b) = @_; return $a + $b }
@a = (1, 2);
print sum (@a, 3), "\n";
5
I'll bet that even an experienced Perl programmer is going to take a
moment to figure out what's going on there. It turns out that you're
telling Perl that the arguments to sum *have* to be scalars. So it's
therefore interpreting @a as a scalar, and the scalar value of an array is
the number of elements it contains. So you end up adding 2 (number of
elements in @a) and 3.
Note no warnings. You won't get any even with use strict and -w; this is
what prototypes are supposed to do. And this is actually useful in some
very limited circumstances. But it's very subtle and hard to follow.
Personally, I only use prototypes when I'm doing it for some of the syntax
that you can only achieve with prototypes. For example, you can declare a
sub with a prototype of (\@) and then pass in an array with function(@var)
and instead of getting the contents of the array, you'll get a reference
to the actual array. That's often *very* useful and hard to do without
prototypes. But for normal Perl code, my experience is that prototypes
are more confusing and inflexible than you really want, and that they tend
to produce odd errors that people debugging Perl programs don't expect.
--
Russ Allbery (rra@stanford.edu) <URL:http://www.eyrie.org/~eagle/>