How to retrieve a scalar name in a foreach loop

E

Eric Pement

I have a question that's really bugging me. I've tried looking in the
Perl FAQ, the Perl Cookbook, the White Camel, and the Perl How-to
under words like scalars, variables, names, reference, and
dereference. No luck. (Or if the answer was present, I didn't
recognize it.)

What I'd like to do is something like this, where foreach() is
followed by a list of scalars:

$v1 = "foo";
$v2 = "bar";
$v3 = "baz";
foreach my $arg ($v1, $v2, $v3) {
print "name: \\$arg, value: $arg\n";
}

Desired output:

name: $v1, value: foo
name: $v2, value: bar
name: $v3, value: baz

Obviously, \\$arg won't work, and I've tried 15 other constructions
and ways of building the foreach loop, all without success. What's the
ticket here? How do I retrieve the name of the variable instead of its
value?

Now I expect that someone will suggest that I build a hash and then
run "foreach(sort keys %hash)" to retrieve name-value pairs. That's
not perfectly workable for me. What I'm actually doing is debugging
someone else's CGI script of several thousand uncommented lines, and
at key points I need to access the simple scalars that are already
present rather than rewriting everything. In point of fact, the
application calls over a dozen perl scripts and setting files, and I
don't have the time or the mandate to overhaul the entire script. What
I need are some well-placed diagnostics which will be used today and
erased tomorrow, and the answer to this question would really help.

Thanks in advance.
 
G

Greg Bacon

: $v1 = "foo";
: $v2 = "bar";
: $v3 = "baz";
: foreach my $arg ($v1, $v2, $v3) {
: print "name: \\$arg, value: $arg\n";
: }
:
: Desired output:
:
: name: $v1, value: foo
: name: $v2, value: bar
: name: $v3, value: baz

% cat try
#! /usr/local/bin/perl

$v1 = "foo";
$v2 = "bar";
$v3 = "baz";

foreach my $arg (qw/ v1 v2 v3 /) {
my $val = defined $$arg ? $$arg : "<undef>";
print "name: \$$arg, value: $val\n";
}

% ./try
name: $v1, value: foo
name: $v2, value: bar
name: $v3, value: baz

You should feel dirty after such naughtiness. Go take a shower. :)

Hope this helps,
Greg
 
G

Gunnar Hjalmarsson

Greg said:
: $v1 = "foo";
: $v2 = "bar";
: $v3 = "baz";
: foreach my $arg ($v1, $v2, $v3) {
: print "name: \\$arg, value: $arg\n";
: }
:
: Desired output:
:
: name: $v1, value: foo
: name: $v2, value: bar
: name: $v3, value: baz

foreach my $arg (qw/ v1 v2 v3 /) {
my $val = defined $$arg ? $$arg : "<undef>";
print "name: \$$arg, value: $val\n";
}

Or without symrefs:

foreach my $arg (qw/$v1 $v2 $v3/) {
print "name: $arg, value: ", eval $arg, "\n";
}
 
M

Michael Carman

I'd like to do is something like this, where foreach() is
followed by a list of scalars:

$v1 = "foo";
$v2 = "bar";
$v3 = "baz";
foreach my $arg ($v1, $v2, $v3) {
print "name: \\$arg, value: $arg\n";
}

Desired output:

name: $v1, value: foo
name: $v2, value: bar
name: $v3, value: baz

How do I retrieve the name of the variable instead of its value?

Are the variables globals or lexicals? If they're lexicals, you
(typically) don't. The variable names aren't stored anyplace normally
accessible. That said, the PadWalker module may do what you want. I've
never used it, so I can't give you any pointers there. Check the docs
and search the newsgroup archives for examples.

If the variables are globals, you could walk the symbol table. Quick &
dirty example:

#!/rfs/apps/bin/perl5.6.1 -w
use strict;
use warnings;

our $v1 = 'foo';
our $v2 = 'bar';
our $v3 = 'baz';

foreach my $arg ($v1, $v2, $v3) {
for my $vn (keys %main::) {
no strict 'refs';
if (*{"*main::$vn"}{SCALAR} eq \$arg) {
print "name: \$$vn, value = '$arg'\n";
}
}
}
__END__
name: $v1, value = 'foo'
name: $v2, value = 'bar'
name: $v3, value = 'baz'

-mjc
 
T

Tassilo v. Parseval

Also sprach Gunnar Hjalmarsson:
Or without symrefs:

foreach my $arg (qw/$v1 $v2 $v3/) {
print "name: $arg, value: ", eval $arg, "\n";
}

Or with strict-proof symrefs:

use strict;

# those need to be package-qualified (or our()ed or 'use var'ed)
$::v1 = "foo";
$::v2 = "bar";
$::v3 = "baz";

foreach my $arg (qw/v1 v2 v3/) {
print "name: \$$arg, value: ${ $::{ $arg } }\n";
}

Not that strictures would matter here a lot, though.

Tassilo
 
G

Gunnar Hjalmarsson

Tassilo said:
Also sprach Gunnar Hjalmarsson:


Or with strict-proof symrefs:

use strict;

# those need to be package-qualified (or our()ed or 'use var'ed)
$::v1 = "foo";
$::v2 = "bar";
$::v3 = "baz";

foreach my $arg (qw/v1 v2 v3/) {
print "name: \$$arg, value: ${ $::{ $arg } }\n";
}

Not that strictures would matter here a lot, though.

But if the variables OP is exploring include lexically scoped
variables, symrefs isn't such a good idea, right?
 
E

Eric Pement

Gunnar Hjalmarsson said:
foreach my $arg (qw/$v1 $v2 $v3/) {
print "name: $arg, value: ", eval $arg, "\n";
}

This was exactly what I was looking for. Thanks!!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top