1

I am using Getopt::Long to parse command line flags and arguments for a perl script. For certain flags, I need to declare to variables within the script that are only used if that flag has been selected - otherwise they're never used. I want to declare them conditionally, i.e. only if the flag is used so that I don't have a bunch of unused variables sitting around. Here is some example code which doesn't work, but illustrates what I want to do.

use Getopt::Long qw(GetOptions);
my ($f1, $f2, $f3);
GetOptions('f1' => \$f1, 'f2' => \$f2, 'f3' => \$f3);

if($f2){
     #declare some variables needed only if $f2 is turned on
}

Can anyone recommend the correct way to do this?

jms
  • 172
  • 1
  • 8
  • 6
    [Use a hash](https://metacpan.org/pod/Getopt::Long#Options-with-hash-values) instead of a bunch of scalars. – ThisSuitIsBlackNot Jul 13 '15 at 22:02
  • 3
    The correct way is not to do microoptimizations that make your code less readable. – mob Jul 13 '15 at 22:12
  • Ah, a hash makes sense. Thanks for the idea. To be clear, mob was suggesting declaring the variables regardless of the flag value and then just not using them if they aren't needed? – jms Jul 13 '15 at 22:47

2 Answers2

0

You should always declare your variables in the smallest scope possible. A scope in Perl is usually a block.

use strict;
use warnings;

sub foo {
  my $bar = 5;
  say $bar;
}

sub baz {
  my $bar = 23;
  say $bar;
}

foo();
baz();
say $bar; # this will give an error

The above code will give an error "Global symbol "$bar" requires explicit package name" because outside of the blocks $bar is not declared. If you remove the marked line, it will output both values, which are separate from each other.

The same principle should be applied throughout your code. Declare variables as late as possible and in as small a scope as possible (or in the largest neccessary).

simbabque
  • 53,749
  • 8
  • 73
  • 136
0

If I understand correctly, you're trying to save a miniscule amount of memory for no reason. Can't help you there.

If on the other hand, you're trying to catch the use of global variables that shouldn't be used, you can use the following:

use Carp            qw( croak );
use Variable::Magic qw( cast wizard );

use constant DEBUG => 1;

sub deny_access_to_scalar {
    my $name = $_[0];

    cast($_[1], wizard(
        get => sub { croak("Variable $name accessed when it shouldn't"); },
        set => sub { croak("Variable $name accessed when it shouldn't"); },
    ));
}

my $f2 = 1;

my $f2a;
deny_access_to_scalar(f2a => $f2a) if DEBUG && $f2;

$f2a = 123;
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • It's not as much about trying to save memory as it is about trying to make the program elegant and minimal. I guess the best way to do it is by reference only, using a hash like suggested, or like simbabque mentioned trying to make the program more modular using subroutines. – jms Jul 14 '15 at 18:45
  • That makes no sense. What is more minimal than not using a variable? (Using subroutines is not going to help you get rid of the global arguments. Using a hash will makes things worse by evading compile-time name checking while making the code slightly longer.) – ikegami Jul 14 '15 at 18:58