Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

How to import "global" variables into sub-scripts from main script?

by Polyglot (Chaplain)
on Mar 22, 2021 at 09:02 UTC ( [id://11130084]=perlquestion: print w/replies, xml ) Need Help??

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

I'm hoping for an easy, simple answer on this one!

I'm not working with modules--I'm just dividing my script into sections for organizational purposes. It really helps me find things. Declaring variables with our in the main script has always worked just fine. Using or requiring other modules from the main script has also never been a problem, with the possible exception of use utf8; which seems to address the specific file in which it is found. Having put

use strict; use warnings; use CGI;

...etc. all in the main script, and only

use utf8; use CGI qw(-utf8); binmode(STDOUT, ":utf8");

...in the sub-scripts, the sub-scripts have worked just fine. I assumed, as errors were few, that I had been going along just fine and that all was working well.

Until today.

After years of working on this script oblivious to any issue here (could a perl update have done something?), I just discovered that use strict; was ONLY working within the context of the main file, and the require'd files were running bare. This discovery came about as I was trying to debug some recent (rather major) changes I had made to the code, and traced it back to no help from strict.

So, like any good perl coder, I promptly added use strict; to my sub-file--only to cause total mayhem in the error logs, mostly in the form of:

#[Slightly sanitized and greatly truncated...] [Mon Mar 22 01:03:25.470815 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$DEBUG" is not imported at ../MyScript2 +021/MyScript_MySQL.pl line 6.: /var/www/[domain_name_redacted].com/cg +i/MyScript-2021.pl [Mon Mar 22 01:03:25.471028 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$DEBUG" is not imported at ../MyScript2 +021/MyScript_MySQL.pl line 556.: /var/www/[domain_name_redacted].com/ +cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471169 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$newuserpass" is not imported at ../MyS +cript2021/MyScript_MySQL.pl line 560.: /var/www/[domain_name_redacted +].com/cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471225 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$membertable" is not imported at ../MyS +cript2021/MyScript_MySQL.pl line 561.: /var/www/[domain_name_redacted +].com/cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471363 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$newuserpass" is not imported at ../MyS +cript2021/MyScript_MySQL.pl line 577.: /var/www/[domain_name_redacted +].com/cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471415 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$membertable" is not imported at ../MyS +cript2021/MyScript_MySQL.pl line 578.: /var/www/[domain_name_redacted +].com/cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471603 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$DEBUG" is not imported at ../MyScript2 +021/MyScript_MySQL.pl line 619.: /var/www/[domain_name_redacted].com/ +cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471690 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$username" is not imported at ../MyScri +pt2021/MyScript_MySQL.pl line 630.: /var/www/[domain_name_redacted].c +om/cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471733 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$digest" is not imported at ../MyScript +2021/MyScript_MySQL.pl line 631.: /var/www/[domain_name_redacted].com +/cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471776 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$table" is not imported at ../MyScript2 +021/MyScript_MySQL.pl line 632.: /var/www/[domain_name_redacted].com/ +cgi/MyScript-2021.pl [Mon Mar 22 01:03:25.471820 2021] [cgi:error] [pid 1602] [client x.x.9 +3.1:65279] AH01215: Variable "$language" is not imported at ../MyScri +pt2021/MyScript_MySQL.pl line 633.: /var/www/[domain_name_redacted].c +om/cgi/MyScript-2021.pl

As those are intended to be global variables which must pass to the various subroutines in the associated files of the same script, I thought it should be easy to just import them.

Think again!

There seems no way to do so--at least, I have yet to find one. I tried using an "import($DEBUG)" -- is this a "pragma"? -- but it did not work. And when I google "perl import variables", all the results talk about EXPORTING them, not importing.

What's a fellow supposed to do?

My sub-scripts just have grouped sets of subroutines, making it easier for me to locate a particular one and then, after any changes, only uploading that portion--saving bandwidth. For example, here's a piece of one of the require'd files:

use strict 'vars'; use utf8; use CGI qw(-utf8); binmode(STDOUT, ":utf8"); #import($DEBUG); # THIS DIDN'T WORK. #CURRENT SUBS IN THIS FILE sub usrupdatePassword; sub updatePassword; sub updateUserRank; sub connectdb; sub connectdb_login; sub create_login_table; sub query_login_table; sub login; 1; #---------------------------------------- sub usrupdatePassword { # A USER FUNCTION if (($DEBUG) && ($DEBUG<12)) { print qq|<p><span style="font-size: + 16pt;color: #008800">SUB:</span> usrupdatePassword\n</p>| }; my $user = shift @_; my $curpass = shift @_; my $newpass = shift @_; my $valid = &checkLogin_mysql($user,$curpass); my $salt = &getRandomSalt; if (($user) && ($newpass) && ($valid)) { $salt = crypt($newuserpass, $salt); my $statement = qq| UPDATE $membertable SET Password = '$salt' WHE +RE Username='$user'; |; &connectdb_login($statement,'updatePassword'); return "Password updated!"; } else { return "Sorry. Incorrect credentials."; } } #END SUB usrupdatePassword sub updatePassword { # AN ADMIN FUNCTION if (($DEBUG) && ($DEBUG<12)) { print qq|<p><span style="font-size: + 16pt;color: #008800">SUB:</span> updatePassword\n</p>| }; my $authuser = shift @_; my $newpass = shift @_; my $valid = &checkUserExists_mysql($authuser); my $salt = &getRandomSalt; if (($authuser) && ($newpass) && ($valid)) { $salt = crypt($newuserpass, $salt); my $statement = qq| UPDATE $membertable SET Password = '$salt' WHE +RE Username='$authuser'; |; &connectdb_login($statement,'updatePassword'); return "Password updated!"; } else { return "Sorry. Incorrect credentials."; } } #END SUB updatePassword # . . . [TRUNCATED]

How would I legitimately use the $DEBUG variable passed from the main portion of the script? And, honestly, why must a variable be imported that is already declared to be within the "global" scope, and which works just fine without "strict"?

(In my personal experience, "strict" is like proper electrical ground wires: It has generally hurt me more than it has helped. (Yes, I've had a UPS backup damaged by lightning only because it was well grounded--within weeks of when I'd installed the copper grounding rod myself. After that, I never used ground again, and never had another problem in years. Go figure.) I know everyone says you always must use it--just like they'd say about ground wires. But . . . I'm about ready to give up on strict. /rant)

Blessings,

~Polyglot~

Replies are listed 'Best First'.
Re: How to import "global" variables into sub-scripts from main script?
by choroba (Cardinal) on Mar 22, 2021 at 09:27 UTC
    our creates an alias in the current lexical scope. The largest scope Perl knows is the file scope, there's nothing like "script-plus-subscripts scope" (or, as you call it, "global" scope). Use fully qualified names if you want to access variables globally, $main::DEBUG is a valid name (and would clearly signal to me something is wrong).

    The advice to use strict and modules comes from experience. Your specific use case might be different, but I doubt it. I've worked with a large codebase that required scripts instead of using modules - it was a nightmare (See for example Wrong + Right = Even Worse that describes one of the issues it had).

    Feel free to use scripts instead of modules and throw away strict. Just don't be surprised later when everything breaks and no one wants to touch the monster.

    Update: There's another possibility, even more horrible, which makes it possible to access our and even my variables in the included script:

    sub run { my ($f) = @_; open my $in, '<', $f or die $!; my $code = do { local $/; <$in> }; eval $code }

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      I appreciate the prompt response, thank you.

      So, is there really no way to import the variables from the main script? I thought perl was supposed to be good at passing variables.

      I don't have a script named "main". I have no idea what perl would think if I tried $main::DEBUG. Is that supposed to "import" the $DEBUG variable? Would I need to do something more like this:  $MyPerlScript.pl::DEBUG? That just looks tacky and ugly, in my opinion.

      It makes no sense to me that the error message would complain about a variable not having been imported--if in fact it's not possible to "import" a variable in the first place. That's the part that gets me, I guess.

      Blessings,

      ~Polyglot~

        > I don't have a script named "main"

        But you have a package called "main" (unless you declare a package in your main script).

        If you have no idea what Perl would do, try it. You already know how to create a Perl script and run it.

        > That just looks tacky and ugly

        Yes, it looks ugly, because it is ugly.

        Note that Variable "$x" is not imported is not an error, it's a warning. It's explained in perldiag:

        (S misc) With "use strict" in effect, you referred to a global variable that you apparently thought was imported from another module, because something else of the same name (usually a subroutine) is exported by that module. It usually means you put the wrong funny character on the front of your variable.

        Which doesn't seem helpful, so your confusion is understandable. It seems the explanation needs an addition (volunteers?)

        Update: The required sub-scripts should have failed to compile under strict. If you're using do instead of require, you should check $@ and $!.

        map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]
        I don't have a script named "main".

        main is the default package if no package statement has declared any other.

        I have no idea what perl would think if I tried $main::DEBUG.

        This is the "fully qualified" form of a package-global name. It is always valid. Even under strict, fully-qualified package globals can always be accessed with or without pre-declaration. Some examples:

        Win8 Strawberry 5.30.3.1 (64) Mon 03/22/2021 6:33:58 C:\@Work\Perl\monks >perl use strict; use warnings; package Bar { # package-globals can always be accessed in fully-qualified form $main::foo = "hi, i'm assigning this in " . __PACKAGE__ . "\n"; } print "A: this is being printed from default package ", __PACKAGE__, " +\n"; # global $foo not yet declared in main: must access fully-qualified print "B: i'm accessing this from ", __PACKAGE__, ": $main::foo"; our $foo; # declare global $foo in package main print "C: i'm accessing this from ", __PACKAGE__, ": $foo"; ^Z A: this is being printed from default package main B: i'm accessing this from main: hi, i'm assigning this in Bar C: i'm accessing this from main: hi, i'm assigning this in Bar


        Give a man a fish:  <%-{-{-{-<

      Just don't be surprised later when everything breaks and no one wants to touch the monster.

      Whether it breaks or not, or even if I wrote it with the combined impeccable abilities of all you experts here, when I'm no longer able to maintain it, it is highly unlikely that anyone else will; not because they wouldn't want to, but because they don't know the first thing about programming, much less Perl. I honestly do not personally know another Perl programmer. I have never met one in my entire sojourn in this part of the world. My Perl books come from Amazon--from America; I don't recollect seeing any such in bookstores in my area. Perl may be a well-established fact in some parts, but not where I am. Here, people learn Java, or C++, or .NET, etc.

      Your "horrible" possibility looks too scary for me. I don't dare try it.

      Because I have never been able to grasp abstractions like OO, references, etc., I've never seen modules as an option for me. I can only do what I have ability for. If I don't understand something, even copy/pasting from someone else will almost never work for me, as I'm unable to adapt to my needs that which I do not understand in the first place. So I generally do all of my own programming, simple though it may be. For some blessed reason I do usually understand regex quite well--I guess it's not so abstract.

      After a few minutes without strict I was able to find the troublespot and everything is working well again. Strict is still in use in my main script file, as it always was. It causes no problems there, but it throws a fit if brought into any of the sub-files.

      ...ACTUALLY, I just confirmed that redeclaring the globals in the sub-script still allows their values to pass from the main script, and that "strict" seems satisfied with that. Honestly, it smacks of overkill to me to have to declare variables repeatedly--if I were to add "strict" to my other files, the globals would have to be repeated in each of them too (I started with just the main MYSQL sub-script). AND, after adding all those global variables, strict had nothing at all to say--that was the only thing between the script running or not running. It was no idle "warning." It was a "kill script" level error to simply not have redeclared my global variables. I don't find this behavior helpful. I know, I'll probably get a ton of downvotes for speaking my mind, as I have with my other posts here, but I have never been a conformist for the sake of popularity. Now, if "strict" had actually said anything useful to me after I had gotten past the globals issue, i.e. if it had told me something about my code that had earlier escaped my notice, and that was an important weakness, I might have a different view. But, nope. It was just its own rigidity. Everything would have worked fine without it.

      Blessings,

      ~Polyglot~

        Honestly, it smacks of overkill to me to have to declare variables repeatedly
        One of the major functions of strict is to protect against typos in variable names. How can it detect a misspelled variable name if it doesn't know (via a declaration) what the correct name is?

        Your answer seems to be "it should know because I declared it in the master script", but what if I write a different master script which uses your auxiliary script without declaring that variable? Because you split things up into multiple scripts and incorporate them into the master using require, each one needs to be able to stand alone, and that includes making its own variable declarations, as well as setting its own pragmas (strict, warnings, etc.).

        if "strict" had actually said anything useful to me after I had gotten past the globals issue, i.e. if it had told me something about my code that had earlier escaped my notice
        Perl tries, but it can't read your mind. Judging by the additional diagnostic messages for the "not imported" errors, it seems that what Perl thinks went wrong is that you imported some_sub() from another module, then mistakenly referred to it as $some_sub. That's not what you were actually doing, of course, but, since it's what Perl thought you were doing, that's the problem it tried to help you solve.
Re: How to import "global" variables into sub-scripts from main script?
by hippo (Bishop) on Mar 22, 2021 at 11:00 UTC
    (Yes, I've had a UPS backup damaged by lightning only because it was well grounded--within weeks of when I'd installed the copper grounding rod myself. After that, I never used ground again, and never had another problem in years. Go figure.)

    This sounds to me like you have rather misinterpreted the moral of your own story. Because the UPS was well grounded the only thing that went wrong was that the UPS was damaged. If it had not been well grounded your building could have burned down and/or lives could have been lost. The point is that the discharge went through the UPS and straight into the ground, not through your heart or the gas pipes.

    This is a good parallel to draw with strict as it is also there to save you from calamity. There is a small cost of convenience in using it but the potential rewards exceed this many times over.


    🦛

      Sigh. Perhaps a little more context is in order.

      In a third-world country, the electric grid is not what you are acquainted with. Furthermore, being in the tropics, the lightning storms would be tremendously active during rainy season. My copper ground rod was the only thing grounded in the entire house. I believe the lightning actually struck the pond next to the house, and traveled UP the ground rod to my UPS. It was the ONLY thing in the house that was damaged. I'm very grateful that the UPS did save the computer that it was attached to--but I never again dared to ground anything in my house.

      We would sometimes have transient power issues (not surges) where one could measure 270 volts between the ground and the neutral on a 220V system. For these reasons, I never dared to install an electric water heater, preferring to take cold showers than risk electrocution.

      My copper ground rod was very likely the only such ground rod for at least 200 meters radius of my house. Beyond that there may have been a business or two that had one--I don't know. In the housing sector, where I was, likely no one had one. It was an area of relative poverty where many homes would have been condemned by the standards of the West.

      As one person told me after the lightning damaged my UPS, "Sucks to be the best ground around."

      Having no ground isolates one in a similar manner to putting on thick rubber boots before grabbing the electrical wires--as many electricians will do. There are definitely times when one does NOT wish to have any path to ground!

      Blessings,

      ~Polyglot~

Re: How to import "global" variables into sub-scripts from main script?
by jcb (Parson) on Mar 22, 2021 at 22:52 UTC

    As my fellow monks have mentioned, our creates a lexical alias to a global variable. Since you are not using packages, all of your code is ending up (implicitly) in package main.

    In the absence of any package statements, our $DEBUG; declares a lexical alias $DEBUG in the current lexical scope for the global variable $main::DEBUG (or $::DEBUG since main has a special alias at the empty name). That global variable still exists for other lexical scopes, which is why your code worked correctly without strict in the sub-scripts.

    Note that our declares a lexical alias and optionally sets a value for the aliased global. Using our $DEBUG = 1; both declares the alias I described above and sets $DEBUG to 1. Using only our $DEBUG; only declares the alias and does not change the value at all. Since the alias aliases a global variable, that variable will still have whatever value it was previously given. This is different from my $var, which creates a new and different $var each time it is used. In all cases, a variable that has never been assigned reads as an undefined value.

    In brief, since you are not using packages, all you need to do is add "our $DEBUG;" to each of your sub-scripts (and similar lines for other our variables that you want to "import" from the main script). The variables already exist in Perl's symbol table, you only need to create new lexical aliases to them.

    Lastly, this also means that if your sub-scripts have any variables that are not used in other files or the main script, you can declare them with my in the sub-script, and each sub-script can have its own variable, even if two sub-scripts have different my variables with the same name.

      Your explanation++ is very good and clear and may benefit future readers of this thread.

      Unfortunately and for reasons I don't understand, Polyglot cannot use our to declare/alias package globals and also cannot use the fully-qualified form of a package-global variable name to access it. The only solution acceptable to Polyglot is that the behavior of strict be changed so that it may be used in any or all of the constituent text files of the application's source without otherwise altering that source in any way. Again, I don't understand Polyglot's reasoning on this point, but I very much doubt it's likely ever to change.


      Give a man a fish:  <%-{-{-{-<

        My reasoning is quite simple: It follows my understanding of the entire purpose of "strict". Its purpose is to guide the programmer into better, more readable coding practice and to alert the programmer to potential code ambiguities, etc. Of itself, strict appears to offer no other benefit in terms of execution efficiency or operation/functionality of the code itself. As long as strict is helpful, by all means use it--and I typically do. But if it is no longer needed or helpful, there is no sin in not using it. Tools are just that: tools--they are there to be used when you need them. If you have a bad leg, use crutches; when the leg is good, you can put them away.

        It might help some here to understand my point of view to know that I have NEVER, and will probably never in the future either, had anyone work together with me on my code aside from the few and relatively minor snippets that I may have put here on perlmonks in questions from time to time. It is a very remote possibility that such will ever occur, because I don't even know anyone who programs in Perl. I know programmers of other languages--but they would shake their heads at Perl and say that they couldn't help me in that department. Essentially, my code is only ever going to be seen, understood, or maintained, by me. Programming is not my bread and butter. I don't think I've ever earned a penny for it beyond the wages I would have received anyhow for work that I chose to augment with a little coding. My mind is, if it functions well and satisfies my needs, great; if it helps, great; if it only hinders, makes life more difficult, etc., discard it.

        Blessings,

        ~Polyglot~

      Obviously, I was a bit frustrated over some things yesterday--had a bit of a bad day. I'm learning. However, my skepticism regarding the benefits of "use strict;" in this context remains. So far, I have seen no benefit at all in adding it to my subscripts: i.e., the only thing it has done is to require the declarations of variables that Perl already knew and was happy with. Strict has, in the absence of these declarations and until they were added, killed the process so that it won't even run, whereas before it would run flawlessly. Adding the global declarations to each and every subscript, when they were already defined in the main script, has only added multiple KB to my files and seemingly for no additional benefit--no additional change in form or function or even feedback on the script quality. I'm left to wonder how much the added kilobytes affect speed/efficiency of code execution, which causes me to seriously wonder if it might not be best to develop under "strict" then remove the added bloat, including the "use strict;" pragma, once everything is running and fine-tuned--including for the main script, as that would save multiple pages of code that appears to be entirely vestigial in terms of the actual script operation (only there for human readability).

      Thoughts?

      Blessings,

      ~Polyglot~

        I will just offer: using strictures, I use fatal warnings and all, has saved me hundreds of hours (update: maybe thousands, now that I think about it) of time and qualifying variables has cost me a couple dozen. It has also allowed me to keep several jobs because I shipped magnitudes fewer bugs.

        Being “correct” is a chore. Being “incorrect” frequently ends up a living hell.

        Developing with strict and then removing it should have no effect at runtime, but you would likely be better served using a persistent execution environment or ByteLoader then by worrying about the relatively small parsing overhead of use strict; and our.

        The important feature that strict 'vars' provides is that it enforces declaration of variables, which will catch typos. If you mistype if $DEBUG as if $DEGUB, strict 'vars' will cause an error, while running without strict will cause Perl to silently create a "$DEGUB" variable with an initial undefined value.

        Lastly, while our is equivalent to simply running without strict in terms of making global (package) variables available, my actually does alter the semantics of the program. The only bloat you will get from strict is use strict; itself and any use vars or our declarations — all other variable declarations are actually important.

Re: How to import "global" variables into sub-scripts from main script?
by bliako (Monsignor) on Mar 23, 2021 at 10:53 UTC

    Placing all your "shareable" variables in a package (which is not OO) can help you to save lines of code (at least). Btw, making money from code has nothing to do with keeping your mind hussle-free and your program maintainable:

    # package to group all constant, read-only vars like $DEBUG # file is Constants.pm and can be placed in same dir as main script # or in a './lib' dir, make sure to adjust 'use lib...' in any subscri +pt it uses it package Constants; use strict; use warnings; # boilerplate use Exporter; our @ISA = qw/Exporter/; # add here all the variables you want exported our @EXPORT = qw/$CON1 $CON2 $DEBUG/; our $CON1 = 'a constant'; our $CON2 = 'another constant'; our $DEBUG = 1; 1;
    # usage from a so-called sub-script use strict; use warnings; # this is where the Constants.pm file resides relative to the path of +the subscript. # good practices exist for where to place these files, this is just fo +r demo use lib 'lib'; use Constants; print "Debug: $DEBUG\n";
    # test.pl to demo the whole setup # run as perl -I. test.pl use strict; use warnings; do 'lib/subscript.pl'; die "failed $@" if $@;

    In this way you will at least save repeating the our $DEBUG; etc... lines in each of the sub-scripts. (and changing all the subscripts whenever you add a new constant)

    I used the word constant but nothing stops you from modifying those "shareable" variables in package Constants, i.e. use them as read-write without any code change above (if you do then perhaps change the filename to 'Shareable.pm' just to be consistent). Caveat: if you want to add one more worries to your head then do that by all means. AFAIC I try to be as lazy as possible and keep my brain free from keeping track who wrote what and where and in which order. As a first step I would place these variables in a package like above, as a second step I would go OO if they had to be read-write. OO is nothing scary, at least in Perl. It's the best way to encapsulate all your data and keep track of who modifies them. The usual way is to create a function to read and modify these variables, for example:

    package Sharedvariables; use strict; use warnings; sub new { my $class = shift; my $self = { # store here all the variables you want to share with an initial + value 'DEBUG' => 1, }; bless $self, $class; return $self; } # my ($class, $params) = $@; # return bless {} => $class; sub debug { my $self = shift; # optional boilerplate to keep track who called us and from where: my $parent = (caller(1))[3]; if( ! defined($parent) ){ $parent = 'ma +in' } my $whoami = ( caller(0) )[3]; # optional parameter for setting the $DEBUG to a new value # if this new-value is absent the we just return current value of $D +EBUG my $newvalue = shift; if( defined $newvalue ){ warn "$whoami (via $parent) : modifying DEBUG from ".$self->{'DEBU +G'}." to $newvalue"; $self->{'DEBUG'} = $newvalue } return $self->{'DEBUG'} } 1;
    # test it use strict; use warnings; use lib 'lib'; use Sharedvariables; my $SVars = Sharedvariables->new(); print "DEBUG: ".$SVars->debug()."\n"; $SVars->debug(42); print "DEBUG: ".$SVars->debug()."\n";

    And here is a version which requires minimal maintentance, you don't have to modify Sharedvariables.pm if you need to add extra variables:

    package SharedvariablesM; use strict; use warnings; sub new { my $class = shift; my $self = { # we store here all shared variables, but this is done automatic store => {} }; bless $self, $class; return $self; } sub value { my $self = shift; my $name = shift; # optional parameter for setting the $DEBUG to a new value # if this new-value is absent the we just return current value of $D +EBUG my $newvalue = shift; # optional boilerplate to keep track who called us and from where: my $parent = (caller(1))[3]; if( ! defined($parent) ){ $parent = 'ma +in' } my $whoami = ( caller(0) )[3].'()'; my $itsnewname = ! exists $self->{'store'}->{$name}; if( defined $newvalue ){ if( $itsnewname ){ warn "$whoami (via $parent) : creating new variable '$name'..." } else { warn "$whoami (via $parent) : modifying '$name' from ".$self->{' +store'}->{$name}." to $newvalue"; } $self->{'store'}->{$name} = $newvalue } elsif( $itsnewname ){ die "$whoami (via $parent) : you are creating a new shared varia +ble named '$name' without a value unless you have the variable name w +rong!" } return $self->{'store'}->{$name} } # clone ourselves and return new object sub clone { my $self = shift; my $aclone = SharedvariablesM->new(); for my $name (keys %{$self->{'store'}}){ $aclone->value($name, $self->value($name)); } return $aclone } sub toString { my $self = shift; my $ret = __PACKAGE__." here is what I store:\n"; for my $name (sort keys %{$self->{'store'}}){ $ret .= $name . '=>' . $self->{'store'}->{$name} . "\n" } return $ret; } 1;
    # and here is a test usage use strict; use warnings; use lib 'lib'; use SharedvariablesM; my $SVars = SharedvariablesM->new(); for (qw/var1 var2 var3/){ $SVars->value($_, $_); } print $SVars->toString(); my $clone = $SVars->clone(); print $clone->toString();

    disclaimer: scripts are unpolished and not all cases tested. If and when you change your mind about Programming then we can talk further.

    5' Edit: The OO way offers you some more advantages: 1) by cloning the object holding the variables you can keep different copies of these variables for testing purposes. A deep clone must be done if you keep anything more complex than scalars. 2) You can pass the variables object to each sub that needs to read configuration etc. And it's easy to save (serialise) the object to disk and reload it for the next run in order to remember state. Again, without you making any changes when you add an extra variable.

    bw, bliako

      Bliako, thank you. While some here seem bent on forcing me into their mold, or just writing me off and voting me down, you have gone the extra mile to give me a truly useful set of suggestions. While I appreciate the time you spent on all of it, I will likely only be able to implement your first suggestion--that of putting variables into a package and calling that. THAT is something I never knew was possible before, and that sounds like a perfect solution in my use case. I wonder why no one else does it this way or bothered to suggest this possibility. Thank you so much!

      Really, I wish I could do OO programming. I've tried. I've read the chapters on it in "Programming Perl" (Third edition) multiple times, and have made attempts at using it, only to meet with total failure. My syntax errors simply follow my general lack of understanding. It's always been above me. Perhaps if I had an excellent teacher who could once explain it for me in a way that made sense to me, it might be different--but, just like math, the typical case is that the teacher has almost a language and logic of his/her own--one that is too esoteric for many minds. I have managed to use the my $something = $cgi->param('something'); method from the CGI module, but many other modules are too hard for me to grasp. When one needs to start escaping or doubling the "funny characters" in front of the variables, or start using those "->" references, that's usually where I get lost--I no longer have any idea when to use which form.

      But I think I will put that Variables.pm file to practice shortly! (I'd always put all of that at the top of my main script, but it makes a large chunk of material to have to scroll past every time I want to navigate between the required/used files and the code.)

      Blessings,

      ~Polyglot~

        But I think I will put that Variables.pm file to practice shortly

        right but beware that there may be dragons if you modify those variables in subscripts. There may be cases (which I am not aware of, I am not a Perl expert) where changing a package variable will not be reflected to other users of said package (e.g. one of your various subscripts). For read-write variables it's not a good way and I will not use myself.

        some here seem bent on forcing me into their mold

        Oh come on! (respectfully said). From my experience this is hardly the case with PM (compare to Stack overflow by posting this exact question there -- even your super-ground -- good story btw -- will not protect you from the flaming lightnings they will throw at you). Perl is a fertile ground for TIMTOWTDI and Perl culture preaches it. Perl allows you to do a lot of things, even shooting your foot, some people, understandably frown on extremely un-productive or buggy solutions which can lead to future problems (e.g. maintainability). If I may say so (and I don't wish to start a conversation about this side-issue): saying that your case is special because you are the only maintainer, is not an argument to the good points presented here (about general programming practices at least). You are offered good solutions which require that you change some of your programming habits, "change gear", "grow up" as a user of a programming language. Case-in-point is OO (actually the free style of Perl OO). It can reduce code-lines (which you are interested) tremendously by re-using code, it can encapsulate data and transformations which will make your code more maintainable, easier to handle. It does not require super-human abilities but it requires to program along certain "molds". And btw the -> is used just as you will be using it in a hashref (which essentially is what an OO object is, a mere hashtable with data AND subs as values). Try posting a question about OO and see what happens.

        bw, bliako

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: How to import "global" variables into sub-scripts from main script? (Cargo culting red flags)
by Anonymous Monk on Mar 22, 2021 at 11:18 UTC
    A reply falls below the community's threshold of quality. You may see it by logging in.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11130084]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (3)
As of 2024-04-18 23:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found