Search code examples
perlsymbolic-references

How can I create a Perl variable name based on a string?


In Perl, is it possible to create a global variable based on a string?

E.g., if I had a function like:

sub create_glob_var {
    my ($glob_var_str) = @_;
    # something like this ( but not a hash access).
    our ${$glob_var_str};
};

and I called it like:

create_glob_var( "bar" );

How could I modify create_glob_var to actually create a global variable called $bar?

My project is using perl 5.8.5.

EDIT

The following doesn't work:

use strict;
BEGIN {
  sub create_glob_var {
    my ($glob_var_str) = @_;
    no strict 'refs';
    $$glob_var_str = undef;  # or whatever you want to set it to
  }

  create_glob_var("bah");
};

$bah = "blah";

Produces:

Variable "$bah" is not imported at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Global symbol "$bah" requires explicit package name at /nfs/pdx/home/rbroger1/tmp2.pl line 12.
Execution of /nfs/pdx/home/rbroger1/tmp2.pl aborted due to compilation errors.

NOTE I realize that using global variables causes ozone depletion and male pattern baldness. I'm trying to clean up some legacy code that is already completely infected with the use of global variables. One refactor at a time...


Solution

  • If you are trying to clean up old code, you can write a module which exports the required variable(s). Every time you feel the need to invoke create_glob_var, instead add a variable to this package and put that in the import list.

    This will help you keep track of what is going on and how variables are being used.

    package MyVars;
    
    use strict; use warnings;
    
    use Exporter 'import';
    
    our($x, %y, @z);
    
    our @EXPORT_OK = qw( $x %y @z );
    

    The script:

    #!/usr/bin/perl
    
    use strict;use warnings;
    
    use MyVars qw( $x %y @z );
    
    $x = 'test';
    %y = (a => 1, b => 2);
    @z = qw( a b c);
    
    use Data::Dumper;
    print Dumper \($x, %y, @z);
    

    Output:

    $VAR1 = \'test';
    $VAR2 = {
              'a' => 1,
              'b' => 2
            };
    $VAR3 = [
              'a',
              'b',
              'c'
            ];