separate require files for common routines, our, and use strict question

B

Bill

While refactoring some perl files, I decided to put common routines in
a common file and include it with require 'file';

In order to keep variables declared in one module available in the
require file, I decided to use the 'our' keyword.

I have a question about 'use strict' syntax errors while using 'our'
with require files that contain subroutines that refer back to the
'our' variables.
See below:

####### begin file tst1.pl ######

#!/usr/bin/perl -w

use strict;

# using 'our', this is global enough to be seen by the required file
below
our $s;

require 'tst2.pl';

$s = 'world!';

printhello();

####### file ends ########
####### begin file tst2.pl ########

#### why can't I use strict here ????
#use strict;

sub printhello {
print "Hello, $s\n";
}

1;

######### file ends #######

So why can't I use strict in the require file here?
 
B

Ben Morrow

#!/usr/bin/perl -w

It is better to 'use warnings' than to use the -w switch.
use strict;

# using 'our', this is global enough to be seen by the required file
below
our $s;

require 'tst2.pl';

$s = 'world!';

printhello();

####### begin file tst2.pl ########

#### why can't I use strict here ????
#use strict;

sub printhello {
print "Hello, $s\n";
}

1;

You have misunderstood what 'our' does. Its action is slightly
confusing. What it does is declare the given globals *for the current
lexical scope*. If you wish to access the same globals (without
package qualification) from a different lexical scope, you have to
declare them there as well.

So. A little more explanation: first of all, the issue does not depend
on having separate files. Separate blocks will do just as well, so

use strict;

{
our $x;
}
{
$x = 1;
}

will not compile. Secondly, although the variables are only declared
in the current lexical scope, they are global:

use strict;
{
our $x = "hello world\n";
}
{
our $x;
print $x;
}

will print "hello world". If you had used 'my' instead of 'our' the
two '$x's would be different variables, and nothing would be printed.

The most important thing, though, is that you are going about this the
wrong way entirely. The point of splitting the code out into files is
to break it into manageble pieces; this is no use if you then produce
hard-to-follow links between those pieces with random shared
globals. What you should do instead is pass the required data to the
subs as parameters: in the given example, &printhello should be
written

sub printhello {
my $s = shift;
print "Hello, $s\n";
}

.. As a separate issue, it would probably be a good idea if you made
your common code into a Perl5ish module rather than a Perl4ish include
file: it is slightly more complicated, but has many benefits in terms
of keeping your code separate from anyone else's. See perldoc perlmod
for starters.

Ben
 
B

Bill

Ben said:
So. A little more explanation: first of all, the issue does not depend
on having separate files. Separate blocks will do just as well, so

use strict;

{
our $x;
}
{
$x = 1;
}

will not compile. Secondly, although the variables are only declared
in the current lexical scope, they are global:

use strict;
{
our $x = "hello world\n";
}
{
our $x;
print $x;
}

will print "hello world".

This takes some getting used to--the global value is available, but
using the global variable is illegal under strict. Think I'll avoid
'our' until I find a better use for it :).
The most important thing, though, is that you are going about this the
wrong way entirely. The point of splitting the code out into files is
to break it into manageble pieces; this is no use if you then produce
hard-to-follow links between those pieces with random shared
globals. What you should do instead is pass the required data to the
subs as parameters: in the given example, &printhello should be
written

sub printhello {
my $s = shift;
print "Hello, $s\n";
}

Yah, and change all the function calls in the refactored files. Darn :(.

Thanks for the clarification....
 
A

Anno Siegel

Bill said:
Ben Morrow wrote:
[...]
globals. What you should do instead is pass the required data to the
subs as parameters: in the given example, &printhello should be
written

sub printhello {
my $s = shift;
print "Hello, $s\n";
}

Yah, and change all the function calls in the refactored files. Darn :(.

Well, yes. Refactoring is about design improvement, and eliminating
globals is (almost) always a step in that direction.

However, it should happen first (while the code is still in one file),
to simplify the splitting.

A good first step in splitting a source file is to add a pair of {}
around each part while leaving them in place. (If the split-off file
is going to be a module, make that one a BEGIN block.) That way you
can detect (and repair) any file-global lexicals that may cross
the gap.

Anno
 
T

Tad McClellan

Bill said:
Ben Morrow wrote:

This takes some getting used to--the global value is available, but


That is the semantic for all dynamic (package) variables in Perl.

using the global variable is illegal under strict.


Using the _unqualified_ variable name is illegal under strict.

You can access $x as $main::x under strict with no declarations.

Think I'll avoid
'our' until I find a better use for it :).


It's only use is to make "use strict" shut up when you use
the unqualified form of variable access.


See also:

"Coping with Scoping":

http://perl.plover.com/FAQs/Namespaces.html
 

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,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top