ftumsh has asked for the wisdom of the Perl Monks concerning the following question:
Lo,
Given that:
$self->client->param( 'usr_id' ) returns 1
$self->client->param( 'edit_usr_id' ) returns undef, or something
$self->client->param( 'mode' ) returns 'add'
How come the below really screws up the hash:
$self->log(LOGDEBUG, 'EDIT_USER: '. Dumper(
{ state => 'db_user',
usr_id => $self->client->param( 'usr_id' ),
edit_usr_id => $self->client->param( 'edit_usr_id' ),
mode => $self->client->param( 'mode' )
}));
EDIT_USER: $VAR1 = {
'add' => undef,
'usr_id' => '1',
'edit_usr_id' => 'mode',
'state' => 'db_user'
};
And yet doing it this way is as expected:
my $a = $self->client->param( 'edit_usr_id' );
$self->log(LOGDEBUG, 'EDIT_USER: '. Dumper(
{ state => 'db_user',
usr_id => $self->client->param( 'usr_id' ),
edit_usr_id => $a,
mode => $self->client->param( 'mode' )
}));
EDIT_USER: $VAR1 = {
'usr_id' => '1',
'mode' => 'add',
'edit_usr_id' => undef,
'state' => 'db_user'
};
Re: mysterious hash ref result
by BrowserUk (Patriarch) on Jan 12, 2007 at 13:44 UTC
|
In a word, context. Try it like this:
$self->log(LOGDEBUG, 'EDIT_USER: '. Dumper(
{
state => 'db_user',
usr_id => $self->client->param( 'usr_id' ),
edit_usr_id => scalar( $self->client->param( 'edit_usr_id' ) )
+,
mode => $self->client->param( 'mode' )
}
)
);
Assuming that produces the desired result, the problem is that in your first example, you are calling $self->client->param( 'edit_usr_id' ) in a list context, whereas in your second example it is called in a scalar context.
self->client->param( .. ) probably finishes something like:
sub param {
...
return unless exists ...
return ...;
}
That is to say, it executes a bare return statement if the parameter does not exist. In a scalar context, a bare return will assign undef to the scalar (lvalue). In a list context, it will return the 'empty list' (usually denoted by ()), but when an empty list is incorporated into a larger list, it is folded to nothing. Essentially, it disappears. Eg:
Perl> sub x{ return };;
Perl> @b = ( 1,2,'a', x(), 5, 6 );;
Perl> print "@b";;
1 2 a 5 6
Perl> @b = ( 1,2,'a', scalar( x() ), 5, 6 );;
Perl> print "@b";;
Use of uninitialized value in join or string at (eval 13) line 1
1 2 a 5 6
In the former, sub x() is called in a list context, so the return statement returns the empty list and that get folded and disappears making no contribution to the state of @b.
In the latter, it is called in a scalar context, so it returns undef, which causes the 4th element of @b to take the value undef.
Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
"Science is about questioning the status quo. Questioning authority".
In the absence of evidence, opinion is indistinguishable from prejudice.
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
Ah, thank you all very much for that. I did not know that being on the RHS of a => meant list context.
I've tracked down the method and indeed it does return
a list or scalar, depending upon context.
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
Re: mysterious hash ref result
by Util (Priest) on Jan 12, 2007 at 14:00 UTC
|
Perhaps param() is using a bare return on error.
A bare return returns undef or the empty list, depending on the context in which the subroutine was called!
Your second example calls param() in scalar context, so a bare return would give you undef;
Your first example calls param() in list context, so a bare return would give you ().
To help confirm my diagnosis, try replacing your anon-hash constructors {...} with anon-array constructors [...],
and impose scalar context by using scalar directly. By avoiding the hash, you will prevent confusion from the random hash ordering in your dump.
use strict;
use warnings;
...
my $dump_string = Dumper [
### Uncomment one or the other of these two lines.
# edit_usr_id => $self->client->param( 'edit_usr_id' ),
edit_usr_id => scalar( $self->client->param( 'edit_usr_id' ) ),
mode => $self->client->param( 'mode' )
];
$self->log(LOGDEBUG, 'EDIT_USER: '.$dump_string ));
It should give something like:
EDIT_USER: $VAR1 = [
'edit_usr_id',
undef,
'mode',
'add',
];
or: EDIT_USER: $VAR1 = [
'edit_usr_id',
'mode',
'add',
];
Also, you should have gotten a warning about 'Odd number of elements' in your hash assignment in your first example. You do have warnings turned on, don't you?
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: mysterious hash ref result
by ferreira (Chaplain) on Jan 12, 2007 at 13:48 UTC
|
I could not write an example that reproduced this exact behavior, but in the construction:
{ state => 'db_user',
usr_id => $self->client->param( 'usr_id' ),
edit_usr_id => $self->client->param( 'edit_usr_id' ),
mode => $self->client->param( 'mode' )
}
the methods are called in list context, and they may mess with the result if they do not return a list with an odd number of elements. For example,
$ perl -MData::Dump=dump -e '
sub f { (1, 2) };
print dump({ a => f, b => 1 })
'
prints
{ 1 => undef, 2 => "b", a => 1 }
As I told, I could not get the same behavior returning an empty list, but I am still investigating. Maybe if you omitted parts in your explanation, this case fits.
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: mysterious hash ref result
by Anonymous Monk on Jan 12, 2007 at 13:45 UTC
|
use Data::Dumper;
sub nothing { return () }
my %hash = (
state => 'db_user',
usr_id => 1,
edit_usr_id => nothing(),
mode => 'add',
);
warn Dumper\%hash;
%hash = (
state => 'db_user',
usr_id => 1,
edit_usr_id => scalar nothing(),
mode => 'add',
);
warn Dumper\%hash;
__DATA__
$VAR1 = {
'add' => undef,
'usr_id' => 1,
'edit_usr_id' => 'mode',
'state' => 'db_user'
};
$VAR1 = {
'usr_id' => 1,
'mode' => 'add',
'edit_usr_id' => undef,
'state' => 'db_user'
};
| [reply] [Watch: Dir/Any] [d/l] |
Re: mysterious hash ref result
by Herkum (Parson) on Jan 12, 2007 at 13:31 UTC
|
One thing you should not be doing is using $a, that is a special variable that Perl uses. As for the rest of it, there is not enough information for me to understand what is going on for me to help debug it.
| [reply] [Watch: Dir/Any] |
|
|