Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I'm not exactly sure of the term to use in asking this question, I guess "making a variable global" although that's not exactly what I'm trying to do. "Declare variable in parent" maybe?

Basically I put my common subs into a file and require it into all my scripts that need them (like probably everyone else). I am trying to define a global variable in my subs file that acts like it was defined in the main script file.

For some reason when I use syscall, if the variable(s) passed to it aren't declared in my main script, everything crashes.

So basically I need...

script.pl:
#!/usr/bin/perl require "subs.lib";

subs.lib:
$blah = "something";

to behave like...
#!/usr/bin/perl $blah = "something";

Hopefully I explained that good enough.
Thanks.

Replies are listed 'Best First'.
Re: Parental Variables
by Fletch (Bishop) on Feb 25, 2004 at 15:29 UTC
Re: Parental Variables
by halley (Prior) on Feb 25, 2004 at 15:41 UTC
    Define your library as a module, using the use statement instead of a require statement.

    Library:

    package Subs; our $Foo = 3; sub foo { $Foo++; } 1;
    Program:
    use Subs; Subs::foo(); print $Subs::Foo, "\n";
    If you want to then export the symbols &Subs::foo and $Subs::Foo to the main program, you add a little stuff to your library. The Exporter module helps you export certain symbols into the "parent" or calling scope.

    Library:

    package Subs; BEGIN { use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw($Foo &foo); } our $Foo = 3; sub foo { $Foo++ } 1;
    Program:
    use Subs; foo(); print $Foo, "\n";
    For a lot more detail on this process, and other features, check out perlmod (or type perldoc perlmod at your console).

    --
    [ e d @ h a l l e y . c c ]

Re: Parental Variables
by dragonchild (Archbishop) on Feb 25, 2004 at 15:44 UTC
    Check out Exporter. It was designed to explicitly solve the problem you're describing. Also, you don't want require - you want use. Do a little reading, then come back and ask some specific questions after you've tried your hand.

    Also, I'd go ahead and read Programming Perl (aka, the Camel book), published by O'Reilly. You can find it at any bookstore. (I know that every Barnes and Nobles as well as every Borders always have 2-3 copies on the shelves. Plus, Amazon has it for immediate delivery.) It sounds like you know what you want to do, but you're not quite sure how to do it.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

Re: Parental Variables
by ysth (Canon) on Feb 25, 2004 at 16:38 UTC
    You leave out showing the actual problem you are having ("everything crashes"). What do you mean by "using syscall"?

    Depending on your coding style, you may find it necessary to put the require in a BEGIN{} block, or use use instead. Without this, the subs will not be defined until run-time, and the parser will have a harder time deciding what's a function call and what's a bareword or indirect object. Example:

    $ perl -we'require Data::Dumper; print Dumper $^O' Name "main::Dumper" used only once: possible typo at -e line 1. print() on unopened filehandle Dumper at -e line 1.
    vs.
    $ perl -we'use Data::Dumper; print Dumper $^O' $VAR1 = 'cygwin';
    There are many other gotchas like this unless you always make it clear what's a function call &like("this").

    (Without the ampersand but with parentheses will address most of the problem cases; I can't remember the exception(s).)

Re: Parental Variables
by antirice (Priest) on Feb 25, 2004 at 16:17 UTC

    You could do FILENAME but that solution is pretty ugly. You should instead do as the others are recommending and implement it as a module and import it in.

    antirice    
    The first rule of Perl club is - use Perl
    The
    ith rule of Perl club is - follow rule i - 1 for i > 1

Re: Parental Variables
by Anonymous Monk on Feb 25, 2004 at 17:35 UTC
    Thank you for your fast replies.

    Unfortunately I can't use modules (because the person who this is for is a paranoid .... who is scared of the evilness that might be lurking in a module some "hacker" made -- not joking).

    Because of this, I can't use the Time::HiRes module. I'm trying to display the load times of my scripts (in less than seconds). My sub for this is:
    sub getTimeOfDay { syscall(116,$tod,0); my($s,$ms) = unpack("LL",$tod); return $s + $ms / 1000000; } $tod = "\0\0\0\0\0\0\0\0";
    ...and basically I just get the start time and end time and compare them.

    I want to add it to my subs file so I don't have to add that code to every script. The problem is that it won't work (script crashes/error 500/whatever you want to call it) unless $tod is defined in the script itself. The error log contains no information too.

    I tried "do" and it didn't work. I also tried defining $tod in BEGIN and that did work, but the script would crash about 4 out of every 5 times (which I find just weird).

    I've been going crazy reading pages and pages of Perl help on the internet, and I've gotten nowhere, finally decided to ask and that's what I'm doing.
      If you can save a file on the computer your script runs on, you can save a module. A module is no big deal; it is just a file which name normally ends in .pm and which must return the value of '1'.

      It is no different from your .lib file.

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Parental Variables
by talexb (Chancellor) on Feb 25, 2004 at 20:20 UTC

    I just want to throw something out to you, since I came across the same problem recently.

    Are you sure you want to set up (what amounts to) a global variable, or would you rather call a subroutine to get you the value that you want?

    Think about it.

    Alex / talexb / Toronto

    Life is short: get busy!

Re: Parental Variables
by Anonymous Monk on Feb 25, 2004 at 22:12 UTC
    Ok, for testing purposes, I added Exporter to it and ran it off my computer. Now it does what I mentioned before where it runs fine one out of every few tries, but errors the others.

    I don't care if it uses a var or sub, the sub results are going to end up being stored on a var anyway. I just want to gettimeofday at the begining and the end of my scripts without needing to add the code on each script and without using modules. It works fine if I declare the variable within the main script. Everything else is either not working at all, or working 1/4 of the time.