Pls help old perl-monger with new version syntax?

R

r.mariotti

Been doing perl since mid-90's. Just upgraded to the latest version
5.14.2 and many of my perl scripts are thowing errors like no
tomorrow.

I've spent several days trying to resolve the errors without much
success so I thought I would post here as many must have experienced
the same.

I DID research quite extensively with perldoc and google and tried
literally all the suggestions but here it goes anyway.

It appears that using the pragmas warning and strict the newest
version is requiring predefinition of variables prior to their use.

Here's a snippet of my code:

# Define pragmas
use warnings;
use strict;
# Define ALL needed variables & indecies
my $fn = '' unless defined($fn);
my $ln = '' unless defined($ln);
my $opt = '' unless defined($opt);
my $rr = 0 unless defined($rr);
my $x1 = '' unless defined($x1);
my $x2 = '' unless defined($x2);
my $x3 = '' unless defined($x3);
my $x4 = '' unless defined($x4);

Pls note that the '' chars above are two single quotes indicating a
NULL value just to initialize the variables.

The infamous error is

Global symbol "$fn" requires explicit package name

Oh the joy. Anyone care to contribute as it will be very, very
appreciated.

Thanks all
 
R

Rainer Weikusat

(e-mail address removed) writes:

[...]

# Define ALL needed variables & indecies
my $fn = '' unless defined($fn);
[...]

Global symbol "$fn" requires explicit package name

This refers to the $fn used as argument for defined. That's the '$fn'
in the symbol table of the current package, not the my-variable.
 
P

Peter J. Holzer

Been doing perl since mid-90's. Just upgraded to the latest version
5.14.2 and many of my perl scripts are thowing errors like no
tomorrow.

What was the last version of perl you used? Your script doesn't work
with perl 5.8.8 (2006), so it probably doesn't work since at least 5.8.0
(2002).

I've spent several days trying to resolve the errors without much
success so I thought I would post here as many must have experienced
the same.

I DID research quite extensively with perldoc and google and tried
literally all the suggestions but here it goes anyway.

It appears that using the pragmas warning and strict the newest
version is requiring predefinition of variables prior to their use.

Here's a snippet of my code:

# Define pragmas
use warnings;
use strict;
# Define ALL needed variables & indecies
my $fn = '' unless defined($fn);

What are you trying to do here?

defined() doesn't check if a variable exists, it checks whether the
value is (not) undef.

So this means:

if the value of the variable $fn is undef
then
create a new variable $fn in this lexical scope
and assign the empty string to it.

Except that the variable is created at compile time, so it will
always exist in this scope even if there happened to be a variable $fn
with a defined value in an outer scope.

(There is a similar but not quite identical construct for state
variables pre 5.10 - for these, use the new state feature, but I doubt
that this is what you wanted)

I think you just meant

my $fn = '';

hp
 
J

Justin C

Been doing perl since mid-90's. Just upgraded to the latest version
5.14.2 and many of my perl scripts are thowing errors like no
tomorrow.

I've spent several days trying to resolve the errors without much
success so I thought I would post here as many must have experienced
the same.

I DID research quite extensively with perldoc and google and tried
literally all the suggestions but here it goes anyway.

It appears that using the pragmas warning and strict the newest
version is requiring predefinition of variables prior to their use.

Here's a snippet of my code:

# Define pragmas
use warnings;
use strict;
# Define ALL needed variables & indecies
my $fn = '' unless defined($fn);
my $ln = '' unless defined($ln);
my $opt = '' unless defined($opt);
my $rr = 0 unless defined($rr);
my $x1 = '' unless defined($x1);
my $x2 = '' unless defined($x2);
my $x3 = '' unless defined($x3);
my $x4 = '' unless defined($x4);

In addition to what others have said, I think this is
standard practice these days:

my ($fh, $ln, $opt, $x1, $x2, $x3, $x4);
my $rr = 0;

(though it's definitely preferred to declare them
only within the scope of where they're used)


It may be possible to include the declration of $rr
in the first line, but it depends on how it's used.
If it's just a counter, AIUI initialising with: my
$rr; and then later doing: $rr++; would be enough to
make it '1'.

I'm guessing that $x1, $x2, $x3 and $x4 are in some
way related. It may be better to have them in an
array or hash:

my @x;
push @x, where_x1_comes_from();
push @x, where_x2_comes_from();
etc.

or
my %x;
$x{one} = where_x1_comes_from();
$x{two} = where_x2_comes_from()l

....then later:

my $where_i'd_use_x1 = $x[0];
where_i'd_use_x2( $x[1] );

or

my $where_i'd_use_x1 = $x{one};
where_i'd_ise_x2($x{two});

I'm far from good at this stuff, stick around and
watch the experts tear holes in in the above, we'll
both learn something!

Justin.
 
P

Peter J. Holzer

In addition to what others have said, I think this is
standard practice these days:

my ($fh, $ln, $opt, $x1, $x2, $x3, $x4);
my $rr = 0;

Why do you initialize only $rr and not the other variables?

It may be possible to include the declration of $rr
in the first line, but it depends on how it's used.

It also depends on how $fn .. $x4 are used. An empty string is not the
same as undef. If it is important that $fn .. $x4 contain an empty
string, they must be initialized to the empty string. If they can (or
even should) contain undef, then they need not be initialized
explicitely (perl will automatically initialize them to undef). Same for
$rr: If it is important that it contains the number 0, it must be
initialized. If it can contain undef, this is not necessary.

hp
 
R

Rainer Weikusat

Ben Morrow said:
Quoth Justin C <[email protected]>:
[...]
(though it's definitely preferred to declare them
only within the scope of where they're used)

Yes. In general, don't create a variable until you have something useful
to put in it. (This isn't always possible.)

In general, don't declare variables in a lexical scope unless it
happens to be the outmost lexical scope of a subroutine. As soon as
this starts to become unwieldly, structure the code into a set of
subroutines and a controlling superroutine.
 
P

Peter J. Holzer

That isn't quite true. The RHS of the 'unless' is logically before the
start of the scope of the new $fn, so this will indeed test the
definedness of $fn in the outer scope.

Yes, that's what I wrote.

But test will not determine whether a new $fn at the inner scope will be
created, just whether it will be initialized.

Consider:

#!/usr/bin/perl
use warnings;
use strict;
use 5.010;

{
my $fn = 5; # 7

{
my $fn = 3 unless $fn; # 10

say "inner scope: ", $fn; # 12
} # 13
say "outer scope: ", $fn; # 14

} # 16
__END__

This prints:

Use of uninitialized value $fn in say at ./foo line 12.
inner scope:
outer scope: 5

At compile time the compiler sees a my $fn declaration at line 7 and one
at line 10 in nested scopes. So it creates two $fn variables: One with a
scope from line 7 to line 16 and one from line 10 to 13.

It also creates code that assigns 3 to the inner $fn only if the outer
$fn is not true.

So at run time, the interpreter notices that the outer $fn has a true
value (5) and skips the assignment of 3 to the inner $fn. However the
inner $fn still exists with an initial value of undef, und the say at
line 12 will attempt to print that value (which results in a warning).

This is the basis for the old "my $x if 0" hack (but you you know that).

hp
 
R

r.mariotti

Gents,

Thanks for all the good comments. Makes the brain churn even harder.

Here's the skinny on why I asked this:

Again, in most of the perl programs I've created over the years, I
normally have a section near the top of the program where I define the
necessary variables and/or arrays/hashes/etc. In most cases these
fields will be used in the logic that follows and set to the
appropriate value when used. It could be a pointer, a temp variable,
the target of a function, etc.

Not until I began working with this version (5.14.2) included with
Ubuntu 12.04 LTS did I start receiving the referenced error message.
My prior version is what came with Ubuntu 8.04 so I can't say exactly
which one that was. But my existing perl programs did NOT throw that
error back then. Only when I try running them on this new version did
I start seeing this error.

The snippet of code I included in my post was an attempt to come up
with a process that would initialize these fields if they were not
aleady defined. That's why I used the unless defined clause.

My understanding of this function was that it was the perl equivalent
of the php isset function. However, even when I remove the unless
portion of the statements I still receive the same use of
uninitialized variable blah blah.

All I'm trying to do is understand how I can satisfy the syntax so the
programs resume working. They were in production.

So please keep up the comments as I and I'm sure others find them
informative. And if you understand my issue more clearly perhaps more
suggestions will follow.

Thanks
 
X

Xho Jingleheimerschmidt

If that's the only version of perl they provide then find somewhere
else. Versions of perl before 5.8.1 have a known security hole, apart
from anything else (the hash algorithmic complexity attack).

That seems like a vanishingly small use-case as a security hole. It is
mostly a "Want to deny service to your own bad self? Well, go right
ahead, dumb-ass" hole.

The people who are using the vanishingly small use-case, of course,
would be expected to care.

Xho
 
P

Peter J. Holzer

Not until I began working with this version (5.14.2) included with
Ubuntu 12.04 LTS did I start receiving the referenced error message.
My prior version is what came with Ubuntu 8.04 so I can't say exactly
which one that was.

Probably 5.8.8 or 5.10.0. The code you posted definitely wouldn't have
worked with those versions.
But my existing perl programs did NOT throw that
error back then. Only when I try running them on this new version did
I start seeing this error.

The snippet of code I included in my post was an attempt to come up
with a process that would initialize these fields if they were not
aleady defined. That's why I used the unless defined clause.

So this was already an attempt to work around the error message?

Please post a script which did work on Ubuntu 8.04 and which doesn't
work on Ubuntu 12.04.

My understanding of this function was that it was the perl equivalent
of the php isset function.

I don't understand PHP well enough to answer that question. The perl
defined() function is simple: It returns false if its argument is undef,
otherwise true.
However, even when I remove the unless
portion of the statements I still receive the same use of
uninitialized variable blah blah.

So, this script:

# Define pragmas
use warnings;
use strict;
# Define ALL needed variables & indecies
my $fn = '' ;
my $ln = '' ;
my $opt = '' ;
my $rr = 0 ;
my $x1 = '' ;
my $x2 = '' ;
my $x3 = '' ;
my $x4 = '' ;

produces a "use of uninitialized variable" error? I find that hard to
believe.

hp
 
R

Rainer Weikusat

(e-mail address removed) writes:

[...]
The snippet of code I included in my post was an attempt to come up
with a process that would initialize these fields if they were not
aleady defined. That's why I used the unless defined clause.

My understanding of this function was that it was the perl equivalent
of the php isset function. However, even when I remove the unless
portion of the statements I still receive the same use of
uninitialized variable blah blah.

Except that the error produced by your example code was something
different, namely,

Global symbol "$fn" requires explicit package name at a.pl line 5

and so on, for all variables used in it. And this error (not warning)
was caused by the fact that the unless defined(...) sub-statements
were outside of the scope of the my declarations and thus, accessed
undeclared package globals with full qualification.

The 'uninitialized value' (not variable) warning is very likely
produced when an automatic conversion of a so-called 'undefined value'
to either 0 or '' is done at runtime, except in some pretty random
looking subset of situations where this happens to be done. The best
way to deal with that, especially in known-to-be-working code, is

no warnings 'uinitialized';

which disables this warning. Alternatively, you can track down these
uses based on the warning output and include the necessary bogus
initializations to satisfy the coding pharisees ('Korinthenkacker'
would be more apropriate here but I don't know how to translate that
:).
 
R

Rainer Weikusat

Ben Morrow said:
Are you just contradicting me to be contrary, or do you have a point?

The point is that some odd 2x years of experience with it have taught
me that 'functional decomposition' is a good idea. This is also nicely
exposed by the fact that you didn't even try to argue against that but
went straight to the messenger (with a completely nonsensical
supposition -- maybe your wife/ girl friend/ current or perpetual sex
partner of choice argues with you for the sake of outacting
interelational stress, I certainly won't. I don't know you).
 
R

Rainer Weikusat

Ben Morrow said:
I agree entirely. This has nothing to do with whether you declare the
variables in a particular function in a group at the top, or as you need
them.

"I agree entirely. Provided you don't actually do that". As soon as
variables are being declared in inner scopes, a natural candidate for
factoring something out into a new subroutine has been found.
 
J

Justin C

Neither '' nor 0 are the same as undef, so I'm not sure why you've
singled out $rr here...

Of course, thank you for pointing this out. It's just that that is
what I usually do, unless I need to define something explicitly.
I've never had reason to define an empty string, 'undef' has always
been adequate for my needs.

Yes. In general, don't create a variable until you have something useful
to put in it. (This isn't always possible.)

Now you tell me. I've been bending over backwards trying bend some
code to fit 'the rules' ;)


Justin.
 
W

Wolf Behrenhoff

Am 25.07.2012 15:25, schrieb Rainer Weikusat:
"I agree entirely. Provided you don't actually do that". As soon as
variables are being declared in inner scopes, a natural candidate for
factoring something out into a new subroutine has been found.

Just to make sure I understand you correctly: given the two following subs:

sub foo {
...
for my $i (1..100) { ... }
...
}

sub bar {
my $i;
...
for $i (1..100) { ... }
...
}

are you suggesting to prefer bar over foo because in foo the scope for
$i is limited to the loop? Isn't it much better to limit the variable to
the variable to the inner scope of the loop? If the loop does something
"complicated", it is a candidate

I prefer to declare a variable where I need it, this often is an inner
scope. However I agree with Ben and you that 'functional decomposition'
is a good idea and loooong subs should probably be split into smaller ones.

- Wolf
 
W

Wolf Behrenhoff

I said:
If the loop does something
"complicated", it is a candidate

.... for moving it into a new sub, of course. But if it just does some
"simple" operation, I wouldn't move it away.

(sorry, I had accidentally deleted this from the prev posting)
 
R

Rainer Weikusat

Wolf Behrenhoff said:
Am 25.07.2012 15:25, schrieb Rainer Weikusat:

Just to make sure I understand you correctly: given the two following subs:

sub foo {
...
for my $i (1..100) { ... }
...
}

sub bar {
my $i;
...
for $i (1..100) { ... }
...
}

are you suggesting to prefer bar over foo because in foo the scope for
$i is limited to the loop?

There's no variable being declared in an inner scope in either example
so why do you ask? (NB: That's a stupid retort based on tangential
technicalities of the example).
Isn't it much better to limit the variable to the variable to the
inner scope of the loop?

Why?
 
J

Jürgen Exner

Henry Law said:
I long since plonked Herr Weikusat. It's almost fun reconstructing what
he must have said out of irritated posts from people who haven't done
the same.

:)))


jue
 
T

Tim McDaniel

I apologise if my replies are becoming irritating.

No, no! Your posts are almost always valuable. Irritating messages
annoy the recipient; irritated messages are when that annoyed reader
writes about it. Irritated articles are sometimes among the funniest
or most informative. Exemplia gratia, http://notalwaysright.com/ , or
Mark Twain on Cecil Rhodes.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,482
Members
44,901
Latest member
Noble71S45

Latest Threads

Top