Cannot use "my $_" in new version(s) of Perl - perl

In Perl 5.28.1, the following statement is invalid:
>perl
my $_;
Can't use global $_ in "my" at - line 1, near "my $_"
Execution of - aborted due to compilation errors.
This worked at least up to Perl 5.16.3. Was this construct removed from Perl, or is this a bug? If this was removed, I consider that a big problem as this basic construct has been heavily used in the past, and it is also demonstrated in the Perl documentation. Neither Perl history does mention such a big change in the language.

Was this construct removed from Perl, or is this a bug?
From perldoc perlvar:
$_ is a global variable.
However, between perl v5.10.0 and v5.24.0, it could be used lexically
by writing my $_ . Making $_ refer to the global $_ in the same scope
was then possible with our $_ . This experimental feature was removed
and is now a fatal error, but you may encounter it in older code.
If this was removed, I consider that a big problem as ...
I think this is not the right place to discuss this, i.e. discussions would not solve your current problem. As ikegami pointed out in the comments: this feature was marked experimental in 5.18 and thus led to warnings for many years. And you probably just need to replace the my $_ with local $_ in your code.

Related

What is the "once" warnings in perl?

I have code that has,
no warnings 'once';
Reading man warnings I don't see an occurrence of /once/ what does this do?
So long as you don't have strict on, perl allows you to use a variable without declaring it.
perl -wE'$foo = 4;'
Which outputs,
Name main::foo used only once: possible typo at -e line 1.
Note under strict this wouldn't even be permitted,
Global symbol $foo requires explicit package name (did you forget to declare my $foo?) at -e line 1.
You can disable the warning though, without enabling strict by doing no warnings "once"; Though I would suggest strongly you simply remove the unused code instead of silencing the warning.
perl -wE'no warnings "once"; $foo = 4;'
Which both looks ugly and does nothing.
If you run the following you will trigger the warning, plus a little extra explanation:
perl -Mdiagnostics -Mwarnings -e '$foo=1'
The output will be:
Name "main::foo" used only once: possible typo at -e line 1 (#1)
(W once) Typographical errors often show up as unique variable names.
If you had a good reason for having a unique name, then just mention it
again somehow to suppress the message. The our declaration is
provided for this purpose.
NOTE: This warning detects symbols that have been used only once so $c, #c,
%c, *c, &c, sub c{}, c(), and c (the filehandle or format) are considered
the same; if a program uses $c only once but also uses any of the others it
The warning applies to symbol table entries (not "my" lexical variables). If you add -Mstrict to the above, you'll create a strict violation because your variable violates strict 'vars', which prohibits you using a variable that hasn't been declared, with the exception of package globals referred to by their fully-qualified name. If you were to pre-declare $foo with our, the warning goes away:
perl -Mdiagnostics -Mwarnings -Mstrict=vars -E 'our $foo=1'
This works just fine; it avoids a strict violation, and avoids the "once" warning. So the purpose of the warning is to alert you to the use of identifiers that are not declared, not using a fully-qualified name, and also only used once. The objective is to help prevent typos in symbol names, the assumption being that if you use a symbol name only once and have not declared it, it may be a mistake.
Special (punctuation) variables are exempted from this check. You can, therefore, refer to $_ or $/ only once and not trigger a warning. Also, $a and $b are exempt because they are considered special, for use in sort {$a <=> $b} #list; in such constructs they may appear only a single time yet it wouldn't be useful to raise a warning for what is fairly typical code.
You can find the 'once' warning listed in the Warnings Hierarchy here: perldoc warnings.
A list of all diagnostic blurbs is available in perldoc perldiag.

The ?PATTERN? operator is not working for Matching Only Once in Perl

I am new to Perl and am practising some programs. I have encountered a syntax error. Please help me.
My Perl program
#!/usr/bin/perl
#list = qw/ food foosball subeo footnote terfoot canic footbridge /;
foreach ( #list ) {
$first = $1 if ?(foo.*)?;
$last = $1 if /(foo.*)/;
}
print "First: $first, Last: $last\n";
Output
syntax error at MatchingOnlyOnce.pl line 9, near "if ?"
Execution of MatchingOnlyOnce.pl aborted due to compilation errors.
Output of perl -v
This is perl 5, version 24, subversion 1 (v5.24.1) built for MSWin32-x64-multi-t
hread
Copyright 1987-2017, Larry Wall
Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.
Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.
Use
$first=$1 if m?(foo.*)?;
?PATTERN? could be used as a shortcut for m?PATTERN?, but you can no longer omit the match operator's leading m when you use ? as the delimiter.
5.14 deprecated the ability to omit the leading m from m?PATTERN?flags.
5.22 removed the ability to omit the leading m from m?PATTERN?flags.
5.22 and 5.24's perlop lists both m?PATTERN?flags and ?PATTERN?flags, but only the former if legal in these versions.
5.26's documentation will be free of all mentions of ?PATTERN? (as opposed to m?PATTERN?).
If you are not using the default / pattern delimiters, you must specify the match operation as in $x =~ m{...}, $x =~ m!...! etc.
?...? is different than those other alternative delimiters as ?...? does something different than /.../. perldoc perlreref currently states:
?pattern? is like m/pattern/ but matches only once. No alternate delimiters can be used. Must be reset with reset().
That is misleading as Perl used to recognize the plain ?...?, but support for that was completely removed a few years ago:
[perl #120912] [PATCH] Remove support for ?PATTERN? without explicit 'm' operator
…
This has issued a deprecation warning since Perl v5.14 (commit
725a61d70), and precludes using ? as an operator after a unary operator
that defaults to $_, such as:
ref ? $_ : [$_]
Here is the motivation for the deprecation and eventual removal:
Deprecate ?PATTERN?, recommending the equivalent m?PATTERN? syntax, in
order to eventually allow the question mark to be used in new operators
that would currently be ambiguous.
If you are just beginning to learn Perl, you ought to enable strict and warnings. Declare your variables in the smallest applicable scope.
#!/usr/bin/env perl
use strict;
use warnings;
my #list = qw/food foosball subeo footnote terfoot canic footbridge/;
my ($first, $last);
foreach my $item (#list) {
$item =~ m?(foo.*)?
and $first = $1;
$item =~ /(foo.*)/
and $last = $1;
}
print "First: $first, Last: $last\n";
Output:
$ perl tt.pl
First: food, Last: footbridge
A lot of things about Perl are unusual for a programming language, and you have happened upon a corner of the language that is rarely used
Perl was designed by a the linguist Larry Wall, and there are many similarities between Perl and spoken languages. Perl allows abbreviations of some constructs, for instance, a pattern match like
/abc/
is equivalent to
$_ =~ m/abc/
That is to say, if it looks like a regex pattern it will be treated as one, regardless of whether the leading m is there or not. Also, many Perl operators work on $_ by default, which allows you to write a few lines of code without explicitly mentioning a variable
But m?...? is an old-fashioned construct that has really been edged out by lexical variables. If you declare a variable using my then there is no need for the one-shot match, or the corresponding reset operator. It is your declaration that defines the lifetime of the variable
If you are just starting with Perl, I recommend that you
Always start every program with use strict and use warnings 'all'. This isn't optional as it's the first line of defence against simple mistakes and errors
Always declare every variable using my as close as possible to its first use. Occasionally you may want to declare variables before a loop so that its value is kept across iterations, but generally variables should be temporary and useful only for a few lines of code
Forget about m?...?. I have never seen a program that uses it in twenty years of writing Perl professionally
I hope this helps

How can I resolve the warning "Use of assignment to $[ is deprecated"?

I have a program that I downloaded from an older computer to a newer one. It has the following snippet of code:
#!/bin/perl -w
use strict;
$[ = 1; # set array base to 1
$, = ' '; # set output field separator
$\ = "\n"; # set output record separator
However, when I try to run the script I get the following error message:
Use of assignment to $[ is deprecated at ./test.pl line 5.
Any idea on how to resolve this?
I am using the following version of perl:
This is perl 5, version 16, subversion 3 (v5.16.3) built for x86_64-linux-thread-multi
The use of $[ has been discouraged, deprecated, and all but disallowed. See it in perlvar (it is in Deprecated and Removed Variables section†) and see the core arybase where it's been moved.
Still, if you must, you can disable this particular warning category   (Update: only in pre-v5.30)†
use strict;
use warnings;
# Restrict the scope as much as possible
{
no warnings 'deprecated';
$[ = 1; # NOT possible in v5.30+
# ...
}
Now it will not print that warning, and it will work since it is still legal. (Not in v5.30+) †
Note that this also changes other offsets, for strings for example, but not yet some others. It is a very, very old "feature," please read the documentation.
I'd strongly recommend rewriting the script, if at all possible.
†  Still the same status in v5.30   ... but:   "Assigning non-zero to $[ is no longer possible".
Thus you cannot anymore assign, regardless of warnings or errors (those can be suppressed or handled). Then either rewrite the script or use Array::Base if you must work with that offset, as in mob's answer
The module Array::Base implements the array index offset feature in modern versions of perl. For a self-constrained script, beginning the script with
use Array::Base (1);
should behave pretty similarly to an older script that says
$[ = 1;
at the top, but see the docs for some potentially important disclaimers.
Short-term: You can silence this warning by replacing the -w flag (enable some warnings) in the first line with -X (disable all warnings).
Long-term: This script probably just needs to be rewritten entirely. The use of the $[ variable (array base index) has been discouraged since the release of Perl 5.0 (in 1994!!); its presence in this file means that it must be very old indeed.
Since Perl v5.30, assignment to $[ of anything but 0 produces an error. The workaround in zdim's answer no longer applies. The module Array::Base mentioned by mob still works however.

Bizarre copy of UNKNOWN in subroutine entry

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 good, the bad, and the ugly of lexical $_ in Perl 5.10+

Starting in Perl 5.10, it is now possible to lexically scope the context variable $_, either explicitly as my $_; or in a given / when construct.
Has anyone found good uses of the lexical $_? Does it make any constructs simpler / safer / faster?
What about situations that it makes more complicated? Has the lexical $_ introduced any bugs into your code? (since control structures that write to $_ will use the lexical version if it is in scope, this can change the behavior of the code if it contains any subroutine calls (due to loss of dynamic scope))
In the end, I'd like to construct a list that clarifies when to use $_ as a lexical, as a global, or when it doesn't matter at all.
NB: as of perl5-5.24 these experimental features are no longer part of perl.
IMO, one great thing to come out of lexical $_ is the new _ prototype symbol.
This allows you to specify a subroutine so that it will take one scalar or if none is provided it will grab $_.
So instead of writing:
sub foo {
my $arg = #_ ? shift : $_;
# Do stuff with $_
}
I can write:
sub foo(_) {
my $arg = shift;
# Do stuff with $_ or first arg.
}
Not a big change, but it's just that much simpler when I want that behavior. Boilerplate removal is a good thing.
Of course, this has the knock on effect of changing the prototypes of several builtins (eg chr), which may break some code.
Overall, I welcome lexical $_. It gives me a tool I can use to limit accidental data munging and bizarre interactions between functions. If I decide to use $_ in the body of a function, by lexicalizing it, I can be sure that whatever code I call, $_ won't be modified in calling code.
Dynamic scope is interesting, but for the most part I want lexical scoping. Add to this the complications around $_. I've heard dire warnings about the inadvisability of simply doing local $_;--that it is best to use for ( $foo ) { } instead. Lexicalized $_ gives me what I want 99 times out of 100 when I have localized $_ by whatever means. Lexical $_ makes a great convenience and readability feature more robust.
The bulk of my work has had to work with perl 5.8, so I haven't had the joy of playing with lexical $_ in larger projects. However, it feels like this will go a long way to make the use of $_ safer, which is a good thing.
I once found an issue (bug would be way too strong of a word) that came up when I was playing around with the Inline module. This simple script:
use strict qw(vars subs);
for ('function') {
$_->();
}
sub function {
require Inline;
Inline->bind(C => <<'__CODE__');
void foo()
{
}
__CODE__
}
fails with a Modification of a read-only value attempted at /usr/lib/perl5/site_perl/5.10/Inline/C.pm line 380. error message. Deep in the internals of the Inline module is a subroutine that wanted to modify $_, leading to the error message above.
Using
for my $_ ('function') { ...
or otherwise declaring my $_ is a viable workaround to this issue.
(The Inline module was patched to fix this particular issue).
[ Rationale: A short additional answer with a quick summary for perl newcomers that may be passing by. When searching for "perl lexical topic" one can end up here.]
By now (2015) I suppose it is common knowledge that the introduction of lexical topic (my $_ and some related features) led to some difficult to detect at the outset unintended behaviors and so was marked as experimental and then entered into a deprecation stage.
Partial summary of #RT119315:
One suggestion was for something like use feature 'lextopic'; to make use of a new
lexical topic variable:
$^_.
Another point made was that an "implicit name for the topicalizing operator ... other than $_" would work best when combined with explicitly lexical functions (e.g. lexical map or lmap). Whether these approaches would somehow make it possible to salvage given/when is not clear. In the afterlife of the experimental and depreciation phases perhaps something may end up living on in the river of CPAN.
Haven't had any problems here, although I tend to follow somewhat of a "Don't ask, don't tell" policy when it comes to Perls magic. I.e. the routines are not usually expected to rely on their peers screwing with non lexical data as a side effect, nor letting them.
I've tested code against various 5.8 and 5.10 versions of perl, while using a 5.6 describing Camel for occasional reference. Haven't had any problems. Most of my stuff was originally done for perl 5.8.8.