|Do you know where your variables are?|
Aliasing bitesby ambrus (Abbot)
|on May 10, 2005 at 20:31 UTC||Need Help??|
This meditation is a story about how the aliasing semantics of perl has caused me a hard-to-find bug. This is not meant to prove that aliasing is useless, I know how useful it can be in other circumstances.
Suppose I have an array of intermediate results (the numbers below are for illustration only):
While debugging a program, I decided to dump the array at one point of the program. However, I thought that the array could get too large, so I decided to print only the first eight elements. I knew that all the elements of the array were defined, so I decided to do this:
Unexpectedly, this caused a different error in the program, resulting in these messages:
It took me quite a lot of time to figure out what was wrong. The program wasn't running very fast, so I had to wait for its completion after each change. I didn't try to run it with DB, because that would make the program about 4 times slower.
After a while, I figured out that if I change the line to this, the bug disappears:
I was very surprised, because I wouldn't have thought this change could make any difference. But the fact is that the first version has changed the array.
Recall that @root had two elements. This expression
has made the elements @root[2 .. 7] spring into existsance, thus the array has grown to 8 long. This has caused a problem later, when I iterated through @root and tried to use the undefined elements as a hash key.
Now just by saying () = @root[0 .. 7] does not change the length of the array, it just returns undefined values where the elements do not exist. So what's happened here?
Well, the answer is that grep wants to alias the elements of the list to $_ so perl must create a scalar for them.
The same thing can happen with an array element instead of a range, or a hash slice or element. It does not happen with the print operator instead of grep It can also happen with user-defined subroutine instead of print.
There are still issues here I don't understand. I'd be glad if someone could shed some light on how come $a does not exist in the following test program:
Updates: changed code from one-liner to perl -x script, per suggestion of diotalevi. Also added some more readmore tags now that this is frontpaged.
Let me note that I think this is not autovivification, and I tried to explain why in a reply although my explanation isn't very clear.