metaperl has asked for the wisdom of the Perl Monks concerning the following question:

well, In the program below, i am not getting the result prem even though I would expect it.. I justify my expectations after the program:
use Data::Dumper; use strict; use warnings; sub risk_eval { { 'age_22' => 2, 'violations' => '1', 'age_18' => 2, 'dui' => '0', 'insured' => '1', 'major' => 0, 'tickets' => 0 }; } sub _build_risk_type { my($self)=@_; my $E = risk_eval ; my %E = %$E; warn ('risk criteria - ' . Data::Dumper::Dumper(\%E) ) ; $E{age22} && $E{insured} && !$E{sr22} && !$E{dui} && ($E{tickets} +<= 1) && !$E{major} and return 'prem' ; $E{age18} && $E{insured} && !$E{sr22} && !$E{dui} && $E{tickets} < += 3 and return 'std' ; $E{age18} and return 'substd'; die 'No useable risk type found.' } _build_risk_type;
$E{age22}
equals 2... therefore true
$E{insured}
equals 1 therefore true. && of the 2 conditions means we keep going
!$E{sr22}
equals 1 because we negated the empty string found via $E{sr22} so we keep going in this expression
!$E{dui}
equals 1 because we negate the zero in the hashref
$E{tickets} <= 1
is true because $E{tickets} equals 0
!$E{major}
equals true because major is false
so since each part of the boolean expression returns true, why doesnt the expression  return 'prem' execute and end function execution?

note

the line-wrapping in CODE sections is quite distracting. it adds plus-signs in the middle of expressions.

Replies are listed 'Best First'.
Re: boolean chaining - && and 'and'
by si_lence (Deacon) on Jul 29, 2009 at 14:39 UTC
    You got your hash keys wrong. It is age_22 not age22
    cheers, si_lence
Re: boolean chaining - && and 'and'
by kyle (Abbot) on Jul 29, 2009 at 14:40 UTC

    In risk_eval, you spelled it "age_22", but in _build_risk_type, it's spelled "age22". That means that when you get around to testing the condition, $E{age22} is undef (false). I discovered this by using the debugger.

    As an aside, having variables named $E and %E in the same place is somewhat confusing.

Re: boolean chaining - && and 'and'
by ikegami (Patriarch) on Jul 29, 2009 at 14:41 UTC

    $E{age22} isn't true.

    When staring at it doesn't help, you can construct something like this:

    print( $E{age22} ?1:0,"\n"); print( $E{insured} ?1:0,"\n"); print( !$E{sr22} ?1:0,"\n"); print( !$E{dui} ?1:0,"\n"); print( ($E{tickets} <= 1) ?1:0,"\n"); print( !$E{major} ?1:0,"\n");

    Make sure to copy the expressions exactly. Don't retype them.

    Update: I forgot to mention.

    my $E = risk_eval; my %E = %$E;

    can be written as

    my %E = %{ risk_eval() };

    but most people would just work with the reference instead of copying the hash.

      When staring at it doesn't help,

      ... you look out for other tools. What I found very helpful is to place the cursor over an identifier (really any identifier where I expect trouble) and press the * or # key.

      That's the vim command to search for the current identifier as a word, and since I have the option hlsearch enabled, I automatically see all occurrences of this identifier on the current page, and usually I notice if one is missing.

      That's very handy for example to spot typos in package names or hash keys, both of which aren't checked to the same amount at compile time as variables are (assuming you use strict).

Re: boolean chaining - && and 'and'
by GrandFather (Saint) on Jul 29, 2009 at 21:04 UTC

    note

    the long lines are quite unreadable. Use PerlTidy to clean up your source:

    use Data::Dumper; use strict; use warnings; sub risk_eval { return { 'age_22' => 2, 'violations' => '1', 'age_18' => 2, 'dui' => '0', 'insured' => '1', 'major' => 0, 'tickets' => 0 }; } sub _build_risk_type { my ($self) = @_; my $E = risk_eval; my %E = %$E; warn ('risk criteria - ' . Data::Dumper::Dumper (\%E)); $E{age22} && $E{insured} && !$E{sr22} && !$E{dui} && ($E{tickets} <= 1) && !$E{major} and return 'prem'; $E{age18} && $E{insured} && !$E{sr22} && !$E{dui} && $E{tickets} < += 3 and return 'std'; $E{age18} and return 'substd'; die 'No useable risk type found.'; } _build_risk_type;

    Oh, and making the return explicit in risk_eval doesn't hurt readability either.


    True laziness is hard work