Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

how do i create a global var conditionally?

by perltux (Monk)
on Mar 01, 2018 at 14:15 UTC ( [id://1210136] : perlquestion . print w/replies, xml ) Need Help??

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

I would like to create a global variable only if a check returns true, but don't know how.

This is an example of what I mean:

if ($xyz) { my $globalvar; }

which obviously doesn't work as $globalvar will only be local to the it's subroutine.
So how would I rewrite that to create a global variable if $xyz is true, when using 'strict'?

Replies are listed 'Best First'.
Re: how do i create a global var conditionally?
by Eily (Monsignor) on Mar 01, 2018 at 14:23 UTC

    If by global var you mean package var, there's no such thing as declaring them. Perl will happily allow you to use any package var under any circumstance whether already used or not. Simplest thing you can tell for whether a package var is "there" or not, is check if it is defined or not.

    Package global can be recognized by the fact that their name contains the package they belong to, eg $FirstPackage::packageVar or %SecondPackage::alsoAPackageVar. What may look like a package var without the package name are actually aliases with our. If you write our $var; inside the package MyPackage, you're just telling perl that $var actually means $MyPackage::var, but it won't change its value.

Re: how do i create a global var conditionally?
by LanX (Saint) on Mar 01, 2018 at 14:36 UTC
    First my variables aka lexical variable are not global, their access is limited to their scope, which is at most the surrounding file.

    Declarations with my and our are evaluated at compile time, but an if condition only at run-time.

    All ways to execute the if at compile-time (like with BEGIN ) will introduce a surrounding block-scope again.

    You could create a workaround with PadWalker, but still...

    ... the whole question is dubious, there is no point to conditionally declare a lexical variable, because you need to access it somewhere in your compiled code.

    BUT the code won't compile if you access a lexical which wasn't declared before (at least under strict)

    Maybe you should tell us what you really want to achieve... smells a lot like a XY Problem.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Wikisyntax for the Monastery

Re: how do i create a global var conditionally?
by pryrt (Abbot) on Mar 01, 2018 at 14:38 UTC

    Why? Declaring the variable takes virtually no CPU time. A declared but undefined variable doesn't take up much memory. There is nothing I know of that tests for the existence of a variable, so I don't see how you could be using its existence to make a decision later on. Unless you've got a million of these you want to do, I don't see why not just declare the variable all the time, and only define it under the $xyz condition. If you do have a million, your code would be a mess, anyway.

    If you really insist on this, I don't know how to do it with a variable, but it could be done with a key of a global hash:

    use warnings; use strict; my %global; try($_) for 0,0,0,1,0; sub try { my $xyz = shift; if($xyz) { $global{globalvar} = undef; } printf "try(%d) => globalvar %s\n", $xyz, exists $global{globalvar +} ? "exists" : "doesn't exist"; } __END__ try(0) => globalvar doesn't exist try(0) => globalvar doesn't exist try(0) => globalvar doesn't exist try(1) => globalvar exists try(0) => globalvar exists

    Maybe you could do it with eval of some sort, like below... but I'm not sure that line 9 doesn't vivify $main::globalvar anyway.

    use warnings; use strict; my $xyz = 0; if($xyz) { eval { $main::globalvar = undef; print STDERR __LINE__, ": +eval'd\n"} } printf "%d: if(%d) => didn't eval\n", __LINE__, $xyz; $xyz = 1; if($xyz) { eval { $main::globalvar = undef; print STDERR __LINE__, ": +eval'd\n"} } printf "%d: if(%d) => did eval => '%s'\n", __LINE__, $xyz, defined $ma +in::globalvar ? $main::globalvar : '<undef>';

    What is it you're really trying to accomplish with this?

Re: how do i create a global var conditionally?
by ikegami (Patriarch) on Mar 01, 2018 at 15:22 UTC

    You're trying to dynamically generate code.

    perl -e'... if ($xyz) { print "my \$globalbar;\n"; } ...' | perl

    yuck.


    which obviously doesn't work as $globalvar will only be local to the it's subroutine.

    No, its scope is limited to block (curlies) it's in.

Re: how do i create a global var conditionally?
by rizzo (Curate) on Mar 02, 2018 at 15:19 UTC
    Not shure if I get the point here, but it is possible if the global you want to create will be part of an existing array or hash.
    use strict; use warnings; my @globalarray; my $gatekeeper = 1; if($gatekeeper) { push @globalarray, 'foo'; # creates $globalarray[0] } print "$globalarray[0]\n";
      ... the global you want to create ...

      But be aware that  my @globalarray; still declares a lexical variable: it is not visible to any code prior to the point of declaration, and it is not visible in any other source file in the application. If a lexical is declared very early in a source file (update: and if it's not declared in a block scope of any kind, i.e., if it's "in file scope") and if there is only one source file in the application, then a lexical can give a pretty darn good imitation of a global, but it's still a lexical.


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

Re: how do i create a global var conditionally?
by Anonymous Monk on Mar 01, 2018 at 14:22 UTC
    that doesnt make much sense, what do you need it for?
Re: how do i create a global var conditionally?
by perltux (Monk) on Mar 01, 2018 at 20:07 UTC
    Ok thanks all, as I suspected there is no way of doing what I wrote in the first post. Then I'll have to post my problem that led to this in a separate Thread.