Using subroutines as hash dereferences. Bad idea?

D

Derek Basch

I am newer to Perl and am trying to fix someone elses code so I need
some help. When a subroutine returns a hash reference how can you test
for failure of the called subroutine?

For instance if the "pfp_transaction" subroutine fails it will return
scalar 0. Then the interpreter will complain that 0 is a bad hash
reference when it is dereferenced within the "test" subroutine.

sub test {
# bill card
my %ccresult = %{$self->bill_card($ccnum, $ccexp, $amount, $uid)};
}

sub bill_card {
my %ccresult = $self->pfp_transaction(@order_data) || return 0);
return \%ccresult;
}

It seems like it is a very bad idea to use a subroutines return scalar
as a hash dereference because you can't return 0 for error conditions.

Am I correct?

Thanks All,
Derek Basch
 
M

Matt Garrish

Derek Basch said:
I am newer to Perl and am trying to fix someone elses code so I need
some help. When a subroutine returns a hash reference how can you test
for failure of the called subroutine?

Check whether you got a reference to a hash back. If you didn't, it failed.
For instance if the "pfp_transaction" subroutine fails it will return
scalar 0. Then the interpreter will complain that 0 is a bad hash
reference when it is dereferenced within the "test" subroutine.

Which is why you never blindly assume that your subroutines won't fail.
sub test {
# bill card
my %ccresult = %{$self->bill_card($ccnum, $ccexp, $amount, $uid)};
}

sub bill_card {
my %ccresult = $self->pfp_transaction(@order_data) || return 0);
return \%ccresult;
}

It seems like it is a very bad idea to use a subroutines return scalar
as a hash dereference because you can't return 0 for error conditions.

Am I correct?

So long as you check whether you have a reference to a hash - which you
should always do before trying to dereference anything -you can act
accordingly. Look up the ref function in perlfunc.

I don't follow why you would return 0 for failure, though. Did you really
mean the opposite? If you want to have an explicit error flag, then return
an explicit error flag and don't mix the value you want back with a false
condition. In my opinion having a flag is a better mechanism for handling
failures that shouldn't terminate the script, but for short scripts it's
often not worth the effort (especially in this case when the ref function
will do the job).

Matt
 
P

Paul Lalli

Derek said:
I am newer to Perl and am trying to fix someone elses code so I need
some help. When a subroutine returns a hash reference how can you test
for failure of the called subroutine?

That depends on how the subroutine identifies "failure"
For instance if the "pfp_transaction" subroutine fails it will return
scalar 0. Then the interpreter will complain that 0 is a bad hash
reference when it is dereferenced within the "test" subroutine.

sub test {
# bill card
my %ccresult = %{$self->bill_card($ccnum, $ccexp, $amount, $uid)};
}

sub bill_card {
my %ccresult = $self->pfp_transaction(@order_data) || return 0);
return \%ccresult;
}

It seems like it is a very bad idea to use a subroutines return scalar
as a hash dereference because you can't return 0 for error conditions.

That's because you skipped a step. That step being the actual check
for success or failure. You just went right ahead to assuming there
was success and using that return value as a hash reference.

A hash reference is by definition 'true'. 0 is by definition 'false'.
Therefore, if those are the only two possible return values of the
subroutine, just check the truth of the return value:

if (my $hash_ref = bill_card()){
print "$_ => $hash_ref->{$_}\n" for %{$hash_ref};
} else {
die "bill_card() returned a failure\n";
}

Paul lalli
 
D

Derek Basch

Thanks for the replies everyone. This gives me a good place to start
understainding this Perl wackiness.

Derek Basch
 
D

Dave Weaver

Thanks for the replies everyone. This gives me a good place to start
understainding this Perl wackiness.

It's hardly "Perl wackiness". It's no different to the same situation
in C or any other langauge. If your sub can return a failure
condition, you must check for that failure condtion when you call it
or suffer the consquences.
 
D

Dr.Ruud

Derek Basch schreef:
Thanks for the replies everyone. This gives me a good place to start
understainding this Perl wackiness.

Maybe the REFERENCES section of `perldoc perlcheat` would help you?
 

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,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top