dynamically creating a hash from an array

C

ccc31807

To be honest, this may be a FAQ, but I don't seem to have the vocabulary to find it.

Suppose I have a set of variables, like this:
my $username = 'Joe';
my $password = 'somepassword';
my $role = 'user';
my $session = 'q1w2e3r4t5y6';
my $date = '2014-03-21';
my $time = '12345678';

Now, suppose I have a sub that prints the name and value of each variable, like this:
sub debug
{
my $href = shift;
print "-------------begin debugging data------------\n";
foreach my $key (sort keys %{$href})
{
print "$key = $href->{$key}\n";
}
print "-------------end debugging data------------\n";
}

Further, suppose I have an array, like this:
my @debugarray = qw( username password role session date time );

Question: how can I turn the array into a hash so I can pass a reference to the has to the sub? Like this, perhaps:
debug($href);

I suppose that my hash would look like this:
my $href = {
username => $username,
password => password,
role => $role,
session => $session,
date => $date,
time => $time,
};

As I say, this is probably frequently asked, but I may not know how to ask the question. Thanks CC.
 
R

Rainer Weikusat

ccc31807 said:
To be honest, this may be a FAQ, but I don't seem to have the vocabulary to find it.

Suppose I have a set of variables, like this:
my $username = 'Joe';
my $password = 'somepassword';
my $role = 'user';
my $session = 'q1w2e3r4t5y6';
my $date = '2014-03-21';
my $time = '12345678';
[...]

Further, suppose I have an array, like this:
my @debugarray = qw( username password role session date time );

Question: how can I turn the array into a hash so I can pass a reference to the has to the sub? Like this, perhaps:
debug($href);

I suppose that my hash would look like this:
my $href = {
username => $username,
password => password,
role => $role,
session => $session,
date => $date,
time => $time,
};

There's no way to access a 'my' variable 'by name' because at run time,
its "name" is an index into the lexical pad (term?) it belongs to. This
means the only way to achieve this is to generate a string containing
the Perl code creating the anonymous has and executing this code via
eval in a scope where the desired set of my variables exists. Example:

-------------
my $username = 'Joe';
my $password = 'somepassword';
my $role = 'user';
my $session = 'q1w2e3r4t5y6';
my $date = '2014-03-21';
my $time = '12345678';

my @debugarray = qw(username password role session date time);

sub make_hash_init
{
my $code;

$code = '{';
$code .= sprintf('%s => $%s,', $_,$_) for @_;
return $code.'}';
}

my $hdebug = eval(make_hash_init(@debugarray));

printf("%s\t%s\n", $_, $hdebug->{$_}) for keys(%$hdebug);
-------------
 
$

$Bill

Obviously this only gets the content of each var at the time the
hash is created - changing one of them won't change what's in the
hash:

use strict;
use warnings;

my $username = 'Joe';
my $password = 'somepassword';
my $role = 'user';
my $session = 'q1w2e3r4t5y6';
my $date = '2014-03-21';
my $time = '12345678';
my @debugarray = qw(username password role session date time);

my $href;
foreach (@debugarray) { eval "\$href->{$_} = \$$_"; }
debug ($href);
exit;

#- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

sub debug {
my $href = shift;

print "-------------begin debugging data------------\n";
foreach my $key (sort keys %{$href}) {
print "$key = $href->{$key}\n";
}
print "-------------end debugging data------------\n";

}

__END__
 
G

George Mpouras

# here you go

use strict;
use warnings;

my $username = 'Joe';
my $password = 'somepassword';
my $role = 'user';
my $session = 'q1w2e3r4t5y6';
my $date = '2014-03-21';
my $time = '12345678';
my @debugarray = qw( username password role session date time fakevar1
fakevar2);
my %hash;



foreach my $var (@debugarray) {
$_ = eval "\$$var";
$hash{$var} = $_ unless $@
}


use Data::Dumper; print Dumper \%hash;
 
C

Charles DeRykus

To be honest, this may be a FAQ, but I don't seem to have the vocabulary to find it.

Suppose I have a set of variables, like this:
my $username = 'Joe';
my $password = 'somepassword';
my $role = 'user';
my $session = 'q1w2e3r4t5y6';
my $date = '2014-03-21';
my $time = '12345678';

Now, suppose I have a sub that prints the name and value of each variable, like this:
sub debug
{
my $href = shift;
print "-------------begin debugging data------------\n";
foreach my $key (sort keys %{$href})
{
print "$key = $href->{$key}\n";
}
print "-------------end debugging data------------\n";
}

Further, suppose I have an array, like this:
my @debugarray = qw( username password role session date time );

Question: how can I turn the array into a hash so I can pass a reference to the has to the sub? Like this, perhaps:
debug($href);

I suppose that my hash would look like this:
my $href = {
username => $username,
password => password,
role => $role,
session => $session,
date => $date,
time => $time,
};

As I say, this is probably frequently asked, but I may not know how to ask the question. Thanks CC.

See PadWalker for caveats:

use PadWalker qw/peek_my/;
use feature 'say';

my $username = 'Joe';
....
my @debugarray = qw/$username $password $role $session $date $time/;
debug( peek_my(0), \@debugarray );

sub debug {
my ($href, $aref ) = @_;
foreach my $key (@$aref) {
say "$key = ", ${$href->{$key}};
}
}
 
R

Rainer Weikusat

Charles DeRykus said:
[PadWalker]

"I wouldn't recommend using PadWalker directly in production code"

http://search.cpan.org/~robin/PadWalker-1.98

Also mentions "PadWalker is particularly useful for debugging. It's
even used by Perl's built-in debugger..."

So it may be worth the risk here. YMMV.

Being able to replace a tiny bit of 'safe' (in the sense that it works
only with documented interfaces and doesn't fiddle around with internal
data structures of the interpreter) with a fairly large bit of (not
exactly expertly written) C code isn't worth any risks.
 
C

Charles DeRykus

Charles DeRykus said:
[PadWalker]

cool !

"I wouldn't recommend using PadWalker directly in production code"

http://search.cpan.org/~robin/PadWalker-1.98

Also mentions "PadWalker is particularly useful for debugging. It's
even used by Perl's built-in debugger..."

So it may be worth the risk here. YMMV.

Being able to replace a tiny bit of 'safe' (in the sense that it works
only with documented interfaces and doesn't fiddle around with internal
data structures of the interpreter) with a fairly large bit of (not
exactly expertly written) C code isn't worth any risks.

That's overreaching IMO. You're deprecating the value of a module
even used by "Perl's built-in debugger" and especially, in this
case, since the use was limited to debug. You should throw out Perl's
built-in debugger then for the same reason. Caution tips over and
becomes FUD.
 
K

Kaz Kylheku

Charles DeRykus said:
On 3/24/2014 5:31 AM, Rainer Weikusat wrote:

[PadWalker]

cool !

"I wouldn't recommend using PadWalker directly in production code"

http://search.cpan.org/~robin/PadWalker-1.98

Also mentions "PadWalker is particularly useful for debugging. It's
even used by Perl's built-in debugger..."

So it may be worth the risk here. YMMV.

Being able to replace a tiny bit of 'safe' (in the sense that it works
only with documented interfaces and doesn't fiddle around with internal
data structures of the interpreter) with a fairly large bit of (not
exactly expertly written) C code isn't worth any risks.

That's overreaching IMO. You're deprecating the value of a module
even used by "Perl's built-in debugger" and especially, in this
case, since the use was limited to debug. You should throw out Perl's
built-in debugger then for the same reason. Caution tips over and
becomes FUD.

A lexical environment is not something that is passed down to a child function:
doing so (as an exposed feature) makes it a de facto dynamic environment.

Programs that depend on a lexical environment being treated as a dynamic
environment (via some internal escape hatch) should be written with the
understanding that the author is wrecking the lexical scope paradigm.

This falls into the "dumb hack" category when used other than for the intended
purpose of supporting the debugger as part of the implemenation. If Perl ever
becomes a properly compiled language, this area will have to drastically
change, such that programs which depend on it will break.
 
T

Tim McDaniel

Rainer Weikusat wrote [against using PadWalker]

That's overreaching IMO. You're deprecating the value of a module

So far as I've seen, that's Rainer's usual approach to modules from
CPAN, for example, so I'm not surprised to see the same opinion here.

You write that PadWalker is used in the Perl debugger, but
perl -e 'use PadWalker'
fails for me on the systems I have available, so I don't understand
what's going on with it.
 
C

Charles DeRykus

On 3/24/2014 5:31 AM, Rainer Weikusat wrote:

[PadWalker]

cool !

"I wouldn't recommend using PadWalker directly in production code"

http://search.cpan.org/~robin/PadWalker-1.98

Also mentions "PadWalker is particularly useful for debugging. It's
even used by Perl's built-in debugger..."

So it may be worth the risk here. YMMV.

Being able to replace a tiny bit of 'safe' (in the sense that it works
only with documented interfaces and doesn't fiddle around with internal
data structures of the interpreter) with a fairly large bit of (not
exactly expertly written) C code isn't worth any risks.

That's overreaching IMO. You're deprecating the value of a module
even used by "Perl's built-in debugger" and especially, in this
case, since the use was limited to debug. You should throw out Perl's
built-in debugger then for the same reason. Caution tips over and
becomes FUD.

A lexical environment is not something that is passed down to a child function:
doing so (as an exposed feature) makes it a de facto dynamic environment.

Programs that depend on a lexical environment being treated as a dynamic
environment (via some internal escape hatch) should be written with the
understanding that the author is wrecking the lexical scope paradigm.

This falls into the "dumb hack" category when used other than for the intended
purpose of supporting the debugger as part of the implemenation. If Perl ever
becomes a properly compiled language, this area will have to drastically
change, such that programs which depend on it will break.

And the documentation makes it clear that it's particularly useful for
debugging...and not recommended for production code. You need enough
rope to climb into the nooks and crannies of a language even if it's
dangerous and tomorrow you may need a better rope. The "Perl Hacks"
segment on PadWalker shows a couple of cases where breaking
encapsulation is useful and a very apt rationale:

"It's scary and wrong, but sometimes it's just what you need".
 
C

Charles DeRykus

Rainer Weikusat wrote [against using PadWalker]

That's overreaching IMO. You're deprecating the value of a module

So far as I've seen, that's Rainer's usual approach to modules from
CPAN, for example, so I'm not surprised to see the same opinion here.

You write that PadWalker is used in the Perl debugger, but
perl -e 'use PadWalker'
fails for me on the systems I have available, so I don't understand
what's going on with it.

I see in perldebug that using the "y" command requires PadWalker to be
installed.
 
R

Rainer Weikusat

Charles DeRykus said:
Charles DeRykus said:
On 3/24/2014 5:31 AM, Rainer Weikusat wrote:

[PadWalker]

cool !

"I wouldn't recommend using PadWalker directly in production code"

http://search.cpan.org/~robin/PadWalker-1.98

Also mentions "PadWalker is particularly useful for debugging. It's
even used by Perl's built-in debugger..."

So it may be worth the risk here. YMMV.

Being able to replace a tiny bit of 'safe' (in the sense that it works
only with documented interfaces and doesn't fiddle around with internal
data structures of the interpreter) with a fairly large bit of (not
exactly expertly written) C code isn't worth any risks.

That's overreaching IMO. You're deprecating the value of a module
even used by "Perl's built-in debugger" and especially, in this
case, since the use was limited to debug. You should throw out Perl's
built-in debugger then for the same reason. Caution tips over and
becomes FUD.

I didn't write that I thought any risk was associated with using this
module and in fact, I don't think so, except possibly that it may not or
not anymore or not at all be compatible with some Perl versions, IOW,
"it may seem like a free download now but you will have to maintain this
code". Considering that versus

eval('{'.join(',', map { "$_, \$$_" } @a).'}');

this becomes a very bad tradeoff.
 
R

Rainer Weikusat

Rainer Weikusat wrote [against using PadWalker]

That's overreaching IMO. You're deprecating the value of a module

So far as I've seen, that's Rainer's usual approach to modules from
CPAN, for example, so I'm not surprised to see the same opinion here.

That's my usual approach to human gateways answering any Perl question
by (blindly) forwarding something the CPAN search engine returned: It
shifts the topic of discussion away from the original question towards
the 'free download du jour'.
You write that PadWalker is used in the Perl debugger, but
perl -e 'use PadWalker'
fails for me on the systems I have available, so I don't understand
what's going on with it.

According to the documentation, auto-completion of lexical variable
names is provided via PadWalker if it is available. It also seems to be
a core part of the/ an Eclipse Perl debugger.
 
R

Rainer Weikusat

Charles DeRykus said:
On 2014-03-25, Charles DeRykus <[email protected]> wrote:
[...]

[...]
A lexical environment is not something that is passed down to a child function:
doing so (as an exposed feature) makes it a de facto dynamic environment.

Programs that depend on a lexical environment being treated as a dynamic
environment (via some internal escape hatch) should be written with the
understanding that the author is wrecking the lexical scope paradigm.

This falls into the "dumb hack" category when used other than for the intended
purpose of supporting the debugger as part of the implemenation. If Perl ever
becomes a properly compiled language, this area will have to drastically
change, such that programs which depend on it will break.

And the documentation makes it clear that it's particularly useful for
debugging...and not recommended for production code. You need enough
rope to climb into the nooks and crannies of a language even if it's
dangerous and tomorrow you may need a better rope.

Hmm ... sorry, but I don't need any more Perl-level access to the
internal data structures of the interpreter in order to program in Perl/
for perl than I need userspace access to internal kernel data structures
for writing UNIX(*) applications.
The "Perl Hacks" segment on PadWalker shows a couple of cases where
breaking encapsulation is useful and a very apt rationale:

"It's scary and wrong, but sometimes it's just what you need".

The actual example is "dark magic you don't have to understand in order
to use" (this cries out loud for banging some sense into the guy who
wrote this --- there's nothing magical about clumsily written C code
accessing perl data structures and trying to use something one doesn't
understand is a recipe for disaster more of than not) in order to do
something which could have been accomplished by inserting a
print-statement into the example closure or even by running the
unadorned program via perl debugger and using a watch point.
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top