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

Variable Names and References

by chakram88 (Pilgrim)
on Mar 09, 2007 at 15:52 UTC ( [id://603996]=perlquestion: print w/replies, xml ) Need Help??

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

Oh revered monks:

I know I'm missing something silly, but despite reading the Camel References chapter till I'm blurry, and reading the perlref tutorial I am stumped.

I understand hard references wrt using a variable name as a variable. But, if I want to create the variable name on the fly, I can't seem to get the refernce right:

#!/usr/bin/perl -l use warnings; use strict; my $str1 = qq[A-M o'Foo]; my $str2 = qq[.,rtyu_']; my $str3 = qq[$<%^]; my $str4 = qq[this works]; my $ref4 = \$str4; print $$ref4; # works as expected for (1..3) { my $ref = \${'str'.$_}; print "The string is $$ref"; }
outputs:
this works Error:17: Can't use string ("str1") as a SCALAR ref while "strict ref +s" in use

I've tried multiple levels of ref/deref (i.e.  \\\\$var ...  $$$$$ref) but still have the same problem.

What would be the proper way to reference these variables?

Replies are listed 'Best First'.
Re: Variable Names and References
by Joost (Canon) on Mar 09, 2007 at 15:59 UTC
    ${"str$_"} is not a "hard" reference, it's a symbolic reference. i.e. it just refers to the name of a variable. You can't use symbolic refences while you have "strict refs" in use (as the error correctly states).

    You can use symbolic references if you switch off "strict refs":

    for (1..3) { no strict 'refs'; my $ref = \${'str'.$_}; # this creates a hard reference VIA a symb +olic reference # or: my $ref = "str$_"; # this is a purely symbolic reference, +access is the same as above print "The string is $$ref"; }
    update: you can only refer to GLOBALs with symbolic references. (update2: here's the relevant documentation in perlref) That's why that code still won't work. Here's a working version:

    Note that in your example using a simple array would be much easier, less error-prone and more efficient. Symbolic references are almost only useful these days for creating subroutines / packages at runtime (basically, wherever the only alternative is to use eval STRING).

    updated again, added some comments

      huh. Thanks. I understand what you mean about the symbolic reference. I just was not seeing it that way. (hence, while I understood the error message, I thought my problem was in the syntax, when all along it was improper referencing.)

      Thanks. And re your suggestion, I was going to go the route of an array -- but got hung up on why I couldn't make this work.

      Thank you, I can now stop floundering and get back to being productive.

      # or: my $ref = "str$_"; # this is a purely symbolic reference, +access is the same as above
      I don't see how that is a symbolic reference? I think this is (had to think a while to come up with something contrived, here):
      my $class = 'CGI'; my $version; { no strict 'refs'; $version = ${"${class}::VERSION"}; use strict; } print $version # e.g. 3.05 on my machine
      In other words, we construct a variable's name ($CGI::VERSION) out of expanded variables ($class), and expand (it's almost like a string eval()) the result in turn to return the value stored under the constructed variable's name.

      ...mmmm still not really put elegantly, sorry.
        Symbolic references are just names of global variables. That means "str2" is a symolic reference, just like "CGI::VERSION" is.

        In other words; "${class}::VERSION"; is a symbolic reference, and ${"${class}::VERSION"}; derefences the reference into the value of $CGI::VERSION. Note that "hard" references use exactly the same syntax to dereference.

Re: Variable Names and References
by dragonchild (Archbishop) on Mar 09, 2007 at 18:13 UTC
    Any time you find yourself wanting to create variables using a string as the name, you want a hash.

    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      Any time you find yourself wanting to create variables using a string as the name, you want a hash.
      Except when you want an array...
Re: Variable Names and References
by bart (Canon) on Mar 10, 2007 at 12:02 UTC
    I understand hard references wrt using a variable name as a variable. But, if I want to create the variable name on the fly, I can't seem to get the refernce right
    Uh oh. Why on earth would you want to do that? Usually, when people think they want to do this, they don't have a really good reason. But there are plenty of good reasons for not wanting it.
Re: Variable Names and References
by Sartan (Pilgrim) on Mar 09, 2007 at 20:25 UTC
    Aren't we all missing the obvious answer given to us by the compiler?
    You just need to use no strict 'refs';.
    ... { no stict 'refs'; for (1..3) { my $ref = \${'str'.$_}; print "The string is $$ref"; } } ...
    or, as other people suggested, just use a hash.
Re: Variable Names and References
by DrHyde (Prior) on Mar 12, 2007 at 10:26 UTC

    Rule 1: Every time you want to create a variable whose name is decided at runtime, you really want to use a hash;

    Rule 2: If you think you know better, you are wrong;

    Rule 3: No, really

      Against rules 1-3, I always sorta thought of a pointer/reference to a hash object as basically a hash(with certain perks). There don't really seem to be void-ish references.
      Perl creates a runtime error if you take
      $hash = {}
      and try to dereference it as an array or anything else(er well hashes and arrays are about it) such as
      @$hash.
      Perl seems to think a reference to a hash is still a hash but wants to protect the user a bit in terms of nasty memory issues.
      Doing $hash->{ $key } basically acts just like a hash object with slightly different syntax. So $hash->{ 'runtime' . $key } seems like a normal progression.
      D

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (3)
As of 2024-04-24 06:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found