1

What I am trying to ask is easily shown.

Imagine 2 variables named as

my ($foo, $bar) = (0,0);

and

my @a = ("foo","bar","beyond","recognition");

is it possible to string match $a[0] with the variable named $foo, and assign a value to it (say "hi") only if it matches identically?

I am trying to debug this some code (not mine), and I ran into a tough spot. Basically, I have a part of the script where I have a bunch of variables.

my ($p1, $p2, $p3, $p4)= (0,0,0,0);  # *Edited*
my @ids = ("p1","p2","p3","p4")

I have a case where I need to pass each of those variables as a hash key to call a certain operation inside a loop.

for (0..3){
    my $handle = get_my_stuff(@ids);
    my $ret    = $p1->do_something();   # <- $p1 is used for the first instance of loop.
    ...
    ...
    ...
 }

FOr the first iteration of the loop, I need to use $p1, but for the second iteration of the loop I need to pass (or call)

     my $ret  = $p2->do_something(); # not $p1

So what I did was ;

my $p;
for (1..4){
    my $handle = get_my_stuff(@ids);
    no strict 'refs';
    my $ret    = $p{$_}->do_something();
    ...
    ...
    ...
    use strict 'refs';
    ...
  }

But the above operation is not allowed, and I am unable to call my key in such a manner :(. As it turns out, $p1 became a blessed hash as soon after get_my_stuff() was called. And to my biggest surprise, somehow the script in the function (too much and too long to paste here) assign or pass a hash reference to my variables only if they match.

YouHaveaBigEgo
  • 220
  • 6
  • 13
  • `my ($p1, $p2, $p3, $p4)=0 x 4;` will set `$p1` to `"0000"` and all the others to `undef`. `$p{$_}->...` refers to `%p`, not `$p`. Your last code block makes no sense. So `$p1` and so on are objects. And `get_my_stuff` takes a list of names, and returns a list of objects corresponding to those names? Why do you call that in the list? – simbabque Dec 01 '17 at 14:30
  • That was a mistake on my part. I meant to do `($p1, $p2, $p3, $p4)= (0,0,0,0);`. I tried to keep it similar to what the original code was written as. only changed the var names. – YouHaveaBigEgo Dec 01 '17 at 14:35
  • 1
    Please [edit] your question and fix those. It's no use if you don't show your real code, or at least a [mcve] that you have tested to run and produce the result you claim it does. – simbabque Dec 01 '17 at 14:42
  • I followed this example for your second part: https://stackoverflow.com/questions/17434333/using-a-dynamically-generated-variable-name-in-perls-strict-mode – YouHaveaBigEgo Dec 01 '17 at 14:44
  • 1
    Use a hash. If you can. You say you're debugging something that isn't yours, so I don't know what kind of modifications you can / are willing to do. If you really want to refer by name, then I suppose this answers your question: https://stackoverflow.com/a/17434563/6372809 – ilkkachu Dec 01 '17 at 14:52
  • 1
    What you are trying to do is called a symbolic reference. It is not considered to be PBP (Perl Best Practice). Use a hash instead. http://perldoc.perl.org/perlref.html#Symbolic-references – shawnhcorey Dec 02 '17 at 12:59
  • Thank you everyone. – YouHaveaBigEgo Dec 02 '17 at 15:46
  • Please take a moment to read [ask] to learn what to do when someone answers your question. Thanks. :) – simbabque Dec 04 '17 at 10:19

1 Answers1

5

You don't need to try to invent something to deal with variable names. Your idea to use a hash is correct, but your approach is flawed.

It seems your function get_my_stuff takes a list of arguments and transforms them somehow. It then returns a list of objects that correspond to the arguments. Instead of doing that in the loop, do it before you loop through the numbers and build up your hash by assigning each id to an object.

Perl allows you to assign to a hash slice. In that case, the sigil changes to an @. My below implementation uses DateTime with years to show that the objects are different.

use strict;
use warnings;
use feature 'say';
use DateTime;

# for illustration purposes
sub get_my_stuff {
    return map { DateTime->new( year => (substr $_, 1) + 2000 ) } @_;
}


my @ids = qw(p1 p2 p3 p4);
my %p;

# create this outside of the loop
@p{@ids} = get_my_stuff(@ids);

foreach my $i ( 1.. 4 ) {
    say $p{'p' . $i}->ymd; # "do_something"
}

This will output

2001-01-01
2002-01-01
2003-01-01
2004-01-01
simbabque
  • 53,749
  • 8
  • 73
  • 136