Merging potentially undefined hashes

D

Derek Basch

Hi everyone,

I have several functions (getBillingDatabaseAttributes, etc...) that
can either return a hash reference or undefined. They just return a DBI
selectrow_hashref function such as:

$hash_ref = $dbh->selectrow_hashref($statement);

How can I merge these hashes and undefined values?

If I do this:

%hash1 = (%$hash2, %$hash3);

I get a 'cant reference undefined value' error.

Here is my attempt at an idiom to handle this. Haven't tested it:

push(@user_attributes, $self->getBillingDatabaseAttributes($user_id));
push(@user_attributes, $self->getBoardsDatabaseAttributes($user_id));
push(@user_attributes, $self->getMembersDatabaseAttributes($user_id));

foreach (@user_attributes) {
%user_attributes = (@_, %user_attributes);
}

Am I on the right track?
 
B

Ben Morrow

Quoth "Derek Basch said:
Hi everyone,

I have several functions (getBillingDatabaseAttributes, etc...) that
can either return a hash reference or undefined. They just return a DBI
selectrow_hashref function such as:

$hash_ref = $dbh->selectrow_hashref($statement);

How can I merge these hashes and undefined values?

If I do this:

%hash1 = (%$hash2, %$hash3);

I get a 'cant reference undefined value' error.

Do you mean a 'Can't use and undefined value as a HASH reference' error?
Please be precise.
Here is my attempt at an idiom to handle this. Haven't tested it:

push(@user_attributes, $self->getBillingDatabaseAttributes($user_id));
push(@user_attributes, $self->getBoardsDatabaseAttributes($user_id));
push(@user_attributes, $self->getMembersDatabaseAttributes($user_id));

foreach (@user_attributes) {
%user_attributes = (@_, %user_attributes);
}

Am I on the right track?

Well, I would just use

my %hash1 = map %$_, grep defined, $hash2, $hash3;

Ben
 
P

Paul Lalli

Derek said:
I have several functions (getBillingDatabaseAttributes, etc...) that
can either return a hash reference or undefined. They just return a DBI
selectrow_hashref function

Careful with your terminology. They are not returning functions. They
are returning the return value of another function. Rather large
distinction.
such as:

$hash_ref = $dbh->selectrow_hashref($statement);

How can I merge these hashes and undefined values?

If I do this:

%hash1 = (%$hash2, %$hash3);

I get a 'cant reference undefined value' error.

How about:
%hash1 = map { defined $_ ? %{$_} : () } ($hash2, $hash3);

And here's a short-but-complete script that demonstrates its use:
perl -MData::Dumper -e'
$h2 = undef;
$h3 = { foo => q{bar}, baz => q{biff} };
$h4 = undef;
$h5 = { alpha => q{beta} };
%h1 = map { defined $_ ? %{$_} : () } ($h2, $h3, $h4, $h5);
print Dumper(\%h1);
'
$VAR1 = {
'foo' => 'bar',
'baz' => 'biff',
'alpha' => 'beta'
};
Here is my attempt at an idiom to handle this. Haven't tested it:

Why would you post code that you've written but haven't tested? What
was the stumbling block to actually testing it? For all you know, your
code may work perfectly, and you're wasting the time of hundreds of
other people who are reading your question.
push(@user_attributes, $self->getBillingDatabaseAttributes($user_id));
push(@user_attributes, $self->getBoardsDatabaseAttributes($user_id));
push(@user_attributes, $self->getMembersDatabaseAttributes($user_id));

foreach (@user_attributes) {
%user_attributes = (@_, %user_attributes);
}

Am I on the right track?

No. And if you'd run the above code and let Perl tell you what's wrong
with it, you'd know why. There are at least 3 things wrong with the
above code. I leave you to figure out what they are.

Paul Lalli
 
B

Brian McCauley

Derek said:
Hi everyone,

I have several functions (getBillingDatabaseAttributes, etc...) that
can either return a hash reference or undefined. They just return a DBI
selectrow_hashref function such as:

$hash_ref = $dbh->selectrow_hashref($statement);

How can I merge these hashes and undefined values?

If I do this:

%hash1 = (%$hash2, %$hash3);

I get a 'cant reference undefined value' error.

My preferred idiom is:

%hash1 = (%{ $hash2 || {} }, %{ $hash3 || {} });

Or:

%hash1 = (%{\%$hash2}, %{\%$hash3});
 
B

Ben Morrow

Quoth Ben Morrow said:
Do you mean a 'Can't use and undefined value as a HASH reference' error?
Please be precise.

Hoist. Petard.

I meant s/and/an/, of course :)

Ben
 
D

Derek Basch

Ummmm... I was asking people for their ideas on what the proper idiom
to handle this problem was. The code I wrote was simply to convey a
concept because I knew that I was going about it the wrong way. Why
test code that you know is wrong? Especially, when it is only
pseudocode and you clearly state that it is such.

I don't understand why some people on this list are so angry? I wrote
questions just like this on the python list for years and never once
got yelled at. I searched long and hard for previous answers to this
problem and found none. Only then did I post the question.

Anyways, thanks to everyone for the answers. I never would have thought
of these solutions on my own.
 
D

David Squire

Derek said:
Ummmm... I was asking people for their ideas on what the proper idiom
to handle this problem was. The code I wrote was simply to convey a
concept because I knew that I was going about it the wrong way. Why
test code that you know is wrong? Especially, when it is only
pseudocode and you clearly state that it is such.

I don't understand why some people on this list are so angry? I wrote
questions just like this on the python list for years and never once
got yelled at. I searched long and hard for previous answers to this
problem and found none. Only then did I post the question.

....and now you're top-posting. Grrrr.
 
D

Derek Basch

Stupid google groups. I sometimes forget to fix the top posting because
it puts the cursor at the top and auto quote everything below. My
apologies.
 
D

Derek Basch

Stupid google groups. I sometimes forget to fix the top posting because
it puts the cursor at the top and auto quote everything below. My
apologies.
 
D

Derek Basch

Derek said:
Stupid google groups. I sometimes forget to fix the top posting because
it puts the cursor at the top and auto quote everything below. My
apologies.

Hahahhahahaahhahahha. Now i double posted and top posted. Great day for
Derek. Jeez.
 
T

Tad McClellan

Derek Basch said:
I have several functions (getBillingDatabaseAttributes, etc...) that
can either return a hash reference or undefined. They just return a DBI
selectrow_hashref function such as:

$hash_ref = $dbh->selectrow_hashref($statement);


Use the standard idiom for applying a default value:

$hash_ref = $dbh->selectrow_hashref($statement) || {};
 
P

Paul Lalli

Derek said:
Ummmm... I was asking people for their ideas on what the proper idiom
to handle this problem was. The code I wrote was simply to convey a
concept because I knew that I was going about it the wrong way. Why
test code that you know is wrong? Especially, when it is only
pseudocode and you clearly state that it is such.

Uh. You have a different definition of either "clearly" or
"pseudo-code" than I do. Allow me to re-quote you:

That, to you, is the equivalent of "this is pseudo-code"? Sounds to me
like it was an attempt to write real code, but you couldn't be bothered
to type "perl -c" and wanted us to do it for you.
I don't understand why some people on this list are so angry?

Because your post amounted to "I'm lazy and don't feel like checking
this, so please do it for me."
I wrote
questions just like this on the python list for years and never once
got yelled at.

Explain to me where you "got yelled at". Hell, there weren't even any
exclamation marks in my post. Or are you suggesting that anyone who
tells you you're doing something wrong is "yelling" at you?
I searched long and hard for previous answers to this
problem and found none. Only then did I post the question.

Uh-huh, and? I don't recall my post deriding you for not searching
long enough. I asked you why you would write what you believed to be a
way to solve the problem, but didn't even bother testing it. Even if
you knew it was "wrong", you don't think the compiler and run-time
results of such code might lead you to the right answer? Sounds like
you have remarkably little faith in your coding and debugging skills.
Anyways, thanks to everyone for the answers.

You're welcome.

Paul Lalli
 
F

farans

My preferred idiom is:

%hash1 = (%{ $hash2 || {} }, %{ $hash3 || {} });

Or:

%hash1 = (%{\%$hash2}, %{\%$hash3});

I don't uderstand the last one, but I think I prefer this to
"merge hashes and undefined values":

%hash1=(defined $hash2 and defined $hash3) ? (%$hash2, %$hash3) : undef;
 
B

Brian McCauley

farans said:
%hash1=(defined $hash2 and defined $hash3) ? (%$hash2, %$hash3) : undef;

That is wrong in serveral ways.

If both $hash2 and $hash3 are defined it will work correctly.

If either $hash2 are $hash3 are undefined it will ignore the contents
of the other one and set

%hash1 = ( '' => undef)

whilst emitting two warnings.
 
B

Brad Baxter

farans said:
I don't uderstand the last one, ...
From perldoc perlref:
6. References of the appropriate type can spring into
existence if you dereference them in a context that
assumes they exist.

If $hash2 is undefined, you'll get a warning if you attempt
to use it as a hashref, e.g.,
Can't use an undefined value as a HASH reference at -e line 1.

But you do not get a warning if you dereference %$hash2;
rather, a new hash is autovivified and a reference to it is
stored in $hash2.
HASH(0x229a4)

Brian's

takes advantage of this to supply an empty hash, sans
warnings, if the reference begins undefined.

-- Brad
 

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,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top