I just saw some code in our code base (and it's OLD code, as in Perl 3 or Perl 4 days) that looks like this (I'm simplifying greatly):
#array;
push( array, $some_scalar );
Notice that the array in the push() doesn't have an #. I would assume that the code behind push knows that the first argument is supposed to be array so grabs the array from the array typeglob. Is that more or less it? If Perl is able to do that without problem, why would you need to include the # at all?
This is an old 'feature' of the parser. The # isn't mandatory in a push if the variable is a package variable. This is considered by many as a bug that ought to be fixed though. You really shouldn't be doing this.
This is a dubious "feature" of perl, deprecated behaviour; it should be an error, but it works.
If you turn on the warnings of the compiler (perl -W, highly recommended), it warns:
Array #aa missing the # in argument 1 of push() at xx.pl line 2.
Nicholas Clark explains:That's Perl 1 syntax.
Related
I'm hitting a bug in the SVN perl module when using git:
Bizarre copy of UNKNOWN in subroutine entry at
/usr/lib/perl5/vendor_perl/SVN/Base.pm line 80.
And I'm not quite sure if this is a perl bug or a subversion bug. This is the relevant part:
# insert the accessor
if (m/(.*)_get$/) {
my $member = $1;
*{"${caller}::$1"} = sub {
&{"SVN::_${pkg}::${prefix}${member}_". # <<<< line 80
(#_ > 1 ? 'set' : 'get')} (#_)
}
}
(full source)
What is a "Bizarre copy"? And whose fault is it?
Edit: software versions
subversion 1.6.15-1
perl 5.14.0-1
Resolution: This happens when you compile with incompatible flags:
https://groups.google.com/d/msg/subversion_users/EOru50ml6sk/5xrbu3luPk4J
That perldoc gives you the short answer, but a brief STFW session yields a little more detail. This is basically evidence of a smashed stack in Perl.
Trivial example:
#!/usr/bin/perl
my #A = 1..5;
sub blowUp {
undef #A;
my $throwAway = {};
print for #_; # <== line 6
}
blowUp(#A);
__END__
bash$ ./blowitup
Bizarre copy of HASH in print at ./blowitup line 6.
And to make it that much more entertaining, without the $throwAway assignment, it's an invisible error (though under 'use warnings' it will at least still tell you that you're trying to access an uninitialized value). It's just when you make a new assignment that you see the strange behavior.
Since #_ is essentially lexically scoped to the subroutine, and arguments are passed by reference, that little subroutine basically pulls the rug out from under itself by undef'ing the thing that #_ was pointing to (you get the same behavior if you change the undef to an assignment, fwiw). I've found a number of postings on perl5-porters that mention this as an artifact of the fact that items on the stack are not reference counted and therefore not cleanly freed.
So while I haven't looked through all of the code in your full source in depth, I'll go ahead and guess that something in there is messing with something that was passed in on #_ ; then when #_ is referenced again, Perl is telling you that something's rotten in Denmark.
The immediate problem is a bug in the script/module, iow. The deeper issue of Perl not reference counting these items is also there, but I suspect you'll have better luck fixing the module in the short term. :-)
HTH-
Brian
A "Bizarre copy" occurs when Perl's stack is corrupted or contains non-scalars. It occurs as the result of bugs in Perl itself or in XS modules. (Brian Gerard's example exercises one of a long list of known bugs related to the stack not being ref-counted.)
You could isolate the problem by adding the following to the anon sub:
warn("Calling SVN::_${pkg}::${prefix}${member}_".(#_ > 1 ? 'set' : 'get')."...");
You might even want to emit a stack trace, but you might have to build it yourself using caller to avoid triggering the panic when building the stack trace.
Probably a perl bug. SVN::Base has XS components, but the error is occurring in pure-perl code and it's my opinion that perl should never allow it to happen. However, it's possible that there's some weird XS in SVN::Base that's tweaking it.
Best idea: file it against Subversion subcomponent bindings_swig_perl and perlbug both.
The code below is from an old Perl script.
print "%{#{$noss}[$i]}->{$sector} \n\n";
How should I rewrite the code above so that Perl does not complain that "using a hash as a reference is deprecated"? I have tried all sorts of way but I still couldn't quite get the hang of what the Perl compiler want me to do.
print "%{#{$noss}[$i]}->{$sector} \n\n";
should be nothing more than
print "$noss->[$i]{$sector} \n\n";
or even
print "$$noss[$i]{$sector} \n\n";
without all that rigamarole.
Guessing that $noss is a reference to an array of hash references, you can build a correct expression by following the simple rule of replacing
what would normally be an array or hash name (not including the $/#/%) with an expression giving a reference in curly braces.
So your array element, normally $foo[$i], becomes ${$noss}[$i]. That expression is itself a hashref, so to get an element from that hash, instead of $foo{$sector}, you use ${ ${$noss}[$i] }{$sector}.
This can also appear in various other forms, such as $noss->[$i]{$sector}; see http://perlmonks.org?node=References+quick+reference for simple to understand rules.
I agree with ysth and tchrist, and want to reiterate that $noss->[$i]{$sector} really is the best option for you. This syntax is more readable since it shows clearly that $noss is a reference and that you are taking the $ith element of it and further the $sector key from that element.
In terms of teaching to fish rather than giving out fish: you should read perldoc perlreftut and specifically the "use rules". Understanding these two "use rules" along with the extra "arrow rule" (yep only 3 rules) will give you a much better grasp on how to get going with references.
I have this code
if (defined($xml->{account}->{p}) == '2') {
...
}
which gives me this warning
Pseudo-hashes are deprecated at a.pl line 48.
The problem is that in some cases $xml->{account}->{p} doesn't exist, which was why I added the defined function.
$xml is an object, if that makes a difference?
How can this be fixed, so Perl doesn't complain?
Either $xml or $xml->{account} is an ARRAY, not a HASH (you can use ref to check this, see perldoc -f ref). Perl had a now-deprecated feature called "pseudo-hashes" that allowed special arrays to be accessed via hash syntax. If you care about the history, you can google around for it or look at an older-edition camel book.
A recent question used a sigil invariant syntax %hash->{key} = 1; for hash access, which seems to work fine, but I would have thought it would be a syntax error.
It seems to work for arrays as well:
my #array;
#array->[3] = 6;
Is this behavior documented somewhere? I don't remember reading it, but may have overlooked it.
It seems to behave exactly like:
(\%hash)->{key}
rather than what I would have assumed:
(scalar %hash)->{key} # runtime error
Seems this was covered over at perlmonks: http://www.perlmonks.org/?node_id=171177
My reading of perlop has me convinced that this is an unintended
syntactic feature.
And that's exactly what it is. When using the arrow, Perl will see
whatever is left of it as a reference. Including if you have something
like #l or %h.
Note that you will get the warning
Using an array as a reference is deprecated in Perl 5.8.0.
Abigail
I am trying to comprehend the reference/dereference system in Perl.
What I am trying to do is to remove an element by using reference:
my $ref= \#{$collection{$_[0]}};
# delete($$ref[$i]); # delete works, I've tested that already
splice($$ref, $i, 1); # this wouldn't do.
I first tried the delete() subroutine, it works; however, it doesn't shift the index after the removed elements forward by 1, so I cannot continue working on other stuff.
I then Googled and found the splice() subroutine which does delete and shift in one go.
But the error feedback tells me that
"Type of arg 1 to splice must be array (not scalar dereference)..."
I then tried something like this:
splice(#{$$ref}, $i, 1);
That resulted in another error like this:
"Not a SCALAR reference at...(pointing at that line)"
So I am a bit puzzled, how could I handle this issue?
I prefer not using any CPAN or additional library for the solution, if possible.
splice(#$ref, $i, 1); # this works...
Ahhh... I encountered this question last night (2am) so my energy was burnt out...
Now I see the magic in Perl a bit more clearly :)
Sorry about such a simple question.