I present the following evidence that perl is pretty much defective:
1. Too many namespaces, and too much complexity governing which is used when referencing a simple variable.
(Quotations from Programming Perl by Larry Wall et al…)
Perl dictates that scalar variables “be introduced” by a “funny character” and arrays be introduced by a different “funny character.” If Mr. Wall had left it at that, you’d essentially just have some kind of semi-strongly typed language, which would be fine. But it’s not that simple. Consider accessing the arguments passed to your script. Well, they’re put into an array, @ARGV. (The presence of such an array is nice and familiar, if you are willing to overlook the fact that index 0 does not contain the script name, which is instead in magic global variable $0, which bears no relation to the other magic global variables $1 – $9.)
So the following code ought to work, right?
% perl myscript.pl testarg
and myscript.pl:
use strict; use warnings; my $argVal = @ARGV[0];
Nope! That code produces a compile warning: “Scalar value @ARGV[0] better written as $ARGV[0] at myscript.pl line 4.” That’s because “scalar variables are always named with an initial $, even when referring to a scalar that is part of an array or hash.” So the “funny characters” actually serve as a sanity check that the expected thing coming back from rhs expressions are of the type the programmer intended. Ok, that seems like a reasonable safeguard.
This means you can access the memory holding the arguments through either @ARGV or $ARGV[0], $ARGV[1], … depending on whether you want the whole list or an individual one. So you might foolishly think there’s a symbol table somewhere in perl containing the string “ARGV”, pointing to the beginning of the arguments array, upon which offsets are applied when the $ARGV[x] notation is used. Nope! You still don’t know everything you need to in order to use perl variables without surprises (remember the word of Mr. Wall, “what you don’t know won’t hurt you (much).”)
If this was your knowledge, you might still encounter surprises, because in addition to the rule that “scalar variables are always named with a $, even when referring to a scalar that is part of an array or hash”, there is simultaneously the rule that “Every variable type has its own namespace. You can, without fear of conflict, use the same name for a scalar variable, an array, or a hash…” In other words,
- @ARGV the array is in a different namespace from $ARGV the scalar (why did Mr. Wall have to allow that?)
- Yet, to access an element from @ARGV the array, you still have to say $ARGV[n]
- Perl figures out what’s going on through the logic process that the square brackets are evidence you meant the array, @ARGV, even though you said $ARGV.
Thus, the below code:
use strict; use warnings; my $argVal = $ARGV[0]; $ARGV = "hello world"; print "$ARGV\n"; print "$ARGV[0]\n";
…if invoked again as above, produces the below output:
hello world testarg
This behavior is not a special case with @ARGV; any array/scalar with the same names behave this way.
Then there are file and directory handles, which aren’t stored in scalar variables but instead get their own namespaces (yes, more namespace proliferation…you can have a directory handle and a file handle concurrently open and both named the same thing in your code), and they also don’t work like scalar variables, because one does not use a “funny character” when referring to them.
Perhaps “there’s more than one way to do it” could also refer to the multitude of slightly different ways one must use in different situations to refer to a variable…
2. Code can influence what is considered valid code
This is a nuisance when trying to slam together a one-off script in a time crunch and use snippets from other files. Your script is using strict but some other code isn’t? Sorry, gonna have to stop and fix up the other code to work with yours.
Leave a Reply