copying values from a hash into CGI.pm via tied hash reference

I

ioneabu

I am trying to restore values from a saved session to fill in my CGI.pm
fields in the simplest and most generic way possible (such that if I
change my form, I don't have to rewrite this code). This statement did
not work:

$params->{keys %session} = values %session;

$params is a reference to a tied hash returned by Vars().

Here is info on Vars() quoted from

http://stein.cshl.org/WWW/software/CGI/

<quote>
Many people want to fetch the entire parameter list as a hash in which
the keys are the names of the CGI parameters, and the values are the
parameters' values. The Vars() method does this. Called in a scalar
context, it returns the parameter list as a tied hash reference.
Changing a key changes the value of the parameter in the underlying CGI
parameter list. Called in an list context, it returns the parameter
list as an ordinary hash. This allows you to read the contents of the
parameter list, but not to change it.
</quote>

Thanks for help. I know I could do it differently, I was just
wondering why it didn't work this way.

wana
 
M

Matt Garrish

I am trying to restore values from a saved session to fill in my CGI.pm
fields in the simplest and most generic way possible (such that if I
change my form, I don't have to rewrite this code). This statement did
not work:

$params->{keys %session} = values %session;

$params is a reference to a tied hash returned by Vars().

Thanks for help. I know I could do it differently, I was just
wondering why it didn't work this way.

You can't just write something you don't understand and expect it to work:
"keys %session" returns the number of keys in %session in scalar context and
"values %session" returns the number of values (see perlfunc). So, assuming
to two key/value pairs in %session, your statement becomes:

$params->{2} = 2;

If you don't use some kind of loop, you're never going to get what you want:

foreach (keys %session) { $params->{$_} = $session{$_} }

Matt
 
P

Paul Lalli

I am trying to restore values from a saved session to fill in my CGI.pm
fields in the simplest and most generic way possible (such that if I
change my form, I don't have to rewrite this code). This statement did
not work:

"did not work" is a remarkably poor error description. What did it do?
What were you expecting/hoping for it to do? How did the results
differ?

Have you read the posting guidelines that are posted to this group
semi-weekly?
$params->{keys %session} = values %session;

You are using the keys function in a scalar context. In scalar context,
keys returns the number of keys in the given hash. Therefore, if
%session contained two key/value pairs, this is the equivalent of

$params->{2} = 2; #since values in scalar context also returns the
number of pairs

What you want to do is create a hash slice and assign to that. If you
had a normal hash, say:
my %hash;
you would generate the slice like so:
@hash{foo,bar} = ( ... );

The general rule when dealing with hashrefs is to replace the name of
the hash ('hash' in this case) with the hashref, in brackets. Thus
%hash becomes %{$params}
and
@hash{foo,bar} becomes @($params}{foo,bar);

Putting it all together, here's a short example script to demonstrate
the correct technique:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
#fill %session with dummy data
my %session = (foo=>1,bar=>2);
#create anon hash reference
my $params = { };
#create a hashslice and use it to populate the anon hash
@{$params}{keys %session} = values %session;
print Dumper($params);
__END__

$VAR1 = {
'bar' => 2,
'foo' => 1
};


Hope this helps,
Paul Lalli
 
I

ioneabu

Sorry for saying 'did not work.'

Here is what I tried:

$params->{keys %session} = values %session;

Here is the example I based it on:

http://www.unix.org.ua/orelly/perl/learn/ch05_05.htm

<quote>
Hash slices can also be used to merge a smaller hash into a larger one.
In this example, the smaller hash takes precedence in the sense that if
there are duplicate keys, the value from the smaller hash is used:

%league{keys %score} = values %score;
</quote>

Maybe this was the source of my confusion. I thought I understood the
example but now I am not sure.
 
P

Paul Lalli

Matt Garrish said:
If you don't use some kind of loop, you're never going to get what you want:

foreach (keys %session) { $params->{$_} = $session{$_} }

Untrue. A hash slice will do just fine. See my previous response in
this thread. (And no, I haven't benchmarked to see which is faster...)

Paul Lalli
 
P

Paul Lalli

Sorry for saying 'did not work.'

Here is what I tried:

$params->{keys %session} = values %session;

Here is the example I based it on:
<<<SNIPPED PIRATTED BOOK URL>>>

Ah, so you used a piratted copy of material and didn't understand what
it actually did. I'd say that satisfies Karma.
<quote>
Hash slices can also be used to merge a smaller hash into a larger one.
In this example, the smaller hash takes precedence in the sense that if
there are duplicate keys, the value from the smaller hash is used:

%league{keys %score} = values %score;
</quote>

Maybe this was the source of my confusion. I thought I understood the
example but now I am not sure.

Do you understand how the above line of code differs from what you did?
If not, you need to read up on references. Fortunately, Perl comes with
free documentation that you don't have to steal.

At your command line, type
perldoc perlreftut
perldoc perllol
perldoc perldsc
perldoc perlref
(generally in that order)


Paul Lalli
 
I

ioneabu

I didn't realize that was not an official site. I did buy all of the
O'Reilly Perl books plus a few others, so I'm not totally a terrible
person. I did not mean to put a disreputable link into this group.
Sorry again.

$params->{keys %session} = values %session;

hmm...This would be like saying...

${$params}{keys %session} = values %session;

which is accessing an individual hash element which requires a scalar
for the key which puts keys %session into scalar context and is not the
same as:

%hash1{keys %hash2} = values %hash2;

which I assume is special notation for dealing with hash slices. Would
this be the same?

@hash1{keys %hash2} = values %hash2;

Now I am wondering about how to interprete the hash slice notation and
why to use the @ in one case and the % in the other.

Thanks,

wana
 
M

Matt Garrish

Paul Lalli said:
Untrue. A hash slice will do just fine. See my previous response in
this thread. (And no, I haven't benchmarked to see which is faster...)

Fair enough. I was thinking that keys and values wouldn't necessarily return
in the same order when I wrote that, but learned something new today (I'd
still take a loop over a hash slice for clarity, though). And fyi, the time
disparity between the two is minimal, but foreach is slightly faster.

Matt
 
I

ioneabu

I agree with the loop. That is what I finally used in my program since
I realized that I don't necessarily want to share all of the values of
one hash with the other. I needed to do a little filtering along the
way. It is still good for me for learning purposes. Thanks for help.
wana
 
P

Paul Lalli

Matt Garrish said:
Fair enough. I was thinking that keys and values wouldn't necessarily return
in the same order when I wrote that, but learned something new today (I'd
still take a loop over a hash slice for clarity, though). And fyi, the time
disparity between the two is minimal, but foreach is slightly faster.

Just to be clear, keys, values, and each all return the hash's elements
in the same order. That's a guarantee. What that order *is* however,
is unknowable (without digging into the internals of perl itself, I
imagine).

Paul Lalli
 
P

Paul Lalli

Please read the posting guidlines for this group. Specifically, please
quote the message you are responding to. Thank you.
I didn't realize that was not an official site.

If it's not on oreilly.com or perl.com, it's not official.
$params->{keys %session} = values %session;

hmm...This would be like saying...

${$params}{keys %session} = values %session;

which is accessing an individual hash element which requires a scalar
for the key which puts keys %session into scalar context

All correct.
and is not the same as:

%hash1{keys %hash2} = values %hash2;

This is a classic example of "What happened when you tried it?" I
gather that you did not try it, because when I try it, I get:

syntax error at - line 4, near "%hash1{"
which I assume is special notation for dealing with hash slices. Would
this be the same?

@hash1{keys %hash2} = values %hash2;

No. This is the correct way of creating hash slices. The example with
% above is not valid code.
Now I am wondering about how to interprete the hash slice notation and
why to use the @ in one case and the % in the other.

You use % to assign a list of key/value pairs to a hash. You use @ to
create a hash slice - that is, to read or set a list of values based on
a list of keys. (There are no restrictions on the size of that list -
it could be empty, it could contain all of the currently existing hash
keys, it could contain hash keys that do not currently exist).

my %hash = (foo=>1, bar=>2);
is equivalent to:
my %hash;
@hash{foo,bar}=(1,2);

I hope that clears things up,
Paul Lalli
 
I

ioneabu

Thank you very much for taking the time to explain. Through Google,
all answers to my questions have provided an incredibly invaluable
reference in my studies and practice.

Regarding my poor posting practices recently, specifically improper
quoting, this is due to Google's new beta version of groups.google.com.
I prefer it over the old format because posts go up immediately rather
than 6-8 hours.

Unfortunately, replies to a message are done in such a way to make them
non-compliant with comp.lang.perl.misc posting practices.

Try it and see, a little reply box appears at the bottom of the message
you are replying to and that's all you get. I was paying $10 monthly
for a newsgroup service, but I did not need nearly the bandwidth I was
paying for and I had no interest in any kind of large encoded binary
files.

I hope that Google fixes this, I don't know exactly who to complain to.
You would think that such a powerful search engine must use a little
Perl somewhere and that their programmers who spend time here would
have noticed the problem.

wana
 
P

Paul Lalli

Regarding my poor posting practices recently, specifically improper
quoting, this is due to Google's new beta version of groups.google.com.
I prefer it over the old format because posts go up immediately rather
than 6-8 hours.

Unfortunately, replies to a message are done in such a way to make them
non-compliant with comp.lang.perl.misc posting practices.

Try it and see, a little reply box appears at the bottom of the message
you are replying to and that's all you get.

Instead of clicking Reply, click the "Show Options" link, and then click
the Reply link that appears near the top of the message text.

Paul Lalli
 
J

Juha Laiho

Paul Lalli said:
Just to be clear, keys, values, and each all return the hash's elements
in the same order. That's a guarantee. What that order *is* however,
is unknowable (without digging into the internals of perl itself, I
imagine).

Hmm.. is it also so that the order is not necessarily consistent for
two successive runs of the same program? From perldelta for 5.8.1:

: Mainly due to security reasons, the ``random ordering'' of hashes has
: been made even more random. Previously while the order of hash
: elements from keys(), values(), and each() was essentially random, it
: was still repeatable. Now, however, the order varies between different
: runs of Perl.
:
: Perl has never guaranteed any ordering of the hash keys, and the
: ordering has already changed several times during the lifetime of Perl
: 5. Also, the ordering of hash keys has always been, and continues to
: be, affected by the insertion order.

So, the order is constant for a single run of the program, but not
repeatable in consecutive runs.
 
T

Tomi Häsä

Regarding my poor posting practices recently, specifically
improper quoting, this is due to Google's new beta version of
groups.google.com.
[...]

I hope that Google fixes this, I don't know exactly who to
complain to.

If you want to report problems with Google Groups Beta, you can use
this feedback page:

http://groups-beta.google.com/support/bin/request.py

Or you can send email to Google Groups Beta:

(e-mail address removed) (labs-groups2 @ google.com)

Or you can post a message to this discussion group:

http://groups-beta.google.com/group/google-labs-groups2

This message contains a list of some the bugs and problems that have
been reported so far:

http://groups-beta.google.com/group/google-labs-groups2/msg/b54c12517c75eb24

More info in this FAQ:
http://www.geocities.com/googlepubsupgenfaq/#groupsproblems
 

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

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top