in reply to the #include business

In test2.pl, $x is a lexical variable. That means it's only visible within a scope. In this case, since it's not in a block, its scope is the file itself. It will only be visible in nested scopes, never other files.

The easiest way to get this code to work is to use the vars pragma to declare $x as a global variable:

# test1.pl use strict; BEGIN { require 'test2.pl' }; print $x; # test2.pl use strict; use vars '$x'; $x = "this is it\n";

If you're doing something much more complicated, you're better off making a real Perl module and either exporting the variable or making some sort of accessor. The perlmod manpage has some good information.

Replies are listed 'Best First'.
Re: Re: the #include business
by Anonymous Monk on Aug 23, 2003 at 08:21 UTC
    Well, that worked perfectly in my test code. I also see that using use instead of require and renaming the include file to .pm can eliminate the BEGIN block. Then I tried it out in my application. There is a package that is used by several of the independent daemons, and it also needs the global variables we are "including". When I use use or require in both the daemon and the package it "uses", perl recognizes that the include file has already been "used", and won't use it again, so that either the daemon or the package will fail to include the include file, depending upon the order of the use statements in the daemon. Is there a way around this?

      use also calls a class method called import every time it's encountered. You can use Exporter to make variables and functions available to other packages, or you can write your own import routine. I suggest the former.

      package My::Constants; use vars qw( $x $y @EXPORT_OK @ISA ); use strict; use Exporter (); @EXPORT_OK = '$x'; @ISA = 'Exporter'; $x = 'my constant x is a lovable fellow'; $y = 'his ears are green and his belly is yellow'; 1;

      It occurs to me that that's a lot of setup code. There's room for a nicer version of Exporter.

      You could also so something simpler like keep your constants in a package namespace and refer to them that way from other packages and the main daemon. This reduces clutter in the global namespace and only requires the file to be processed once for all of them.

      For example:

      #file1.pl #!/usr/bin/perl -w use strict; use Constants; print "ONE=", $Constants::ONE, "\n"; print "TWO=", $Constants::TWO, "\n"; print "THREE=", $Constants::THREE, "\n"; #Constants.pm package Constants; $Constants::ONE = 1; $Constants::TWO = 2; 1;
      A big problem with this approach is that you don't get compile time checking when you refer to a variable in another package. This is shown above with $Constants::THREE which only causes a problem at run time (at least in Perl 5.6.1).

      Even with that drawback, this is a technique I use.

      -- Eric Hammond

        Constants that you can change...what a novel idea! Of course, you could just do it the "normal" way and use subroutines that are prototyped with no params (or of course use contant).

        package Constants; sub ONE() { 1 } sub TWO() { 2 }