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

Hello there,

I have a simple script to calculate the value of some test conditions on a database, that looks like below:

#!/usr/bin/perl use strict; use warnings; my %cTestH = (); my $dbFile = 'COUNTYDATABASE'; my $timeRng = 'DATERANGE'; my $regionName = 'DISTRICTNAME'; my $A = 'A'; my $B = 'B'; my $C = 'C'; $cTestH{$dbFile}{$timeRng}{$regionName}{$A} = 1; $cTestH{$dbFile}{$timeRng}{$regionName}{$B} = 0; $cTestH{$dbFile}{$timeRng}{$regionName}{$C} = 0; my $bool = 'A&!B&!C'; $bool =~ s/([a-zA-Z]\w*)/\$cTestH\{\$dbFile\}\{\$timeRng\}\{\$regionNa +me\}\{\$1\}/g; print "Evaluating Test Condition: ",$bool,'...',"\n"; print "Result is: ", eval($bool),"\n";

The value of the $bool should have been 1 but instead, Perl's eval function wrongly calculates the value of $bool as 0

What am I doing wrong?

Thank you.

-Layton

Replies are listed 'Best First'.
Re: Perl Boolean Evaluation Shows Incorrect Results
by Tanktalus (Canon) on Mar 01, 2016 at 00:24 UTC

    You're wisely printing out the condition you're about to evaluate right before doing so ... but did you read the output?

    $cTestH{$dbFile}{$timeRng}{$regionName}{$1} - see that $1 there? You escaped the $, so $1 shows up literally. Not what you want. Not sure what you want, but either that \$1 should become $1 or \$$1 - look at the output closely for both of those to see how they turn up and pick the right one for your purposes.

    What I've done in the past is to just replace it with the new value directly, which means getting rid of all them leaning toothpicks: $bool =~ s/([a-zA-Z]\w*)/$cTestH{$dbFile}{$timeRng}{$regionName}{$1}/g; - you end up with much less to evaluate. However, you don't get any short-circuiting if any of the lookups require significant time (e.g., it's a tied hash or you're doing some sort of db lookup or whatever).

      getting rid of all them leaning toothpicks

      Another way to eliminate the leaning toothpicks is to single-quote the non-interpolating part of the replacement string before making the replacement:

      my $rep = '$cTestH{$dbFile}{$timeRng}{$regionName}{'; my $bool = 'A&!B&!C'; $bool =~ s/([a-zA-Z]\w*)/$rep$1}/g;

      Output:

      12:55 >perl 1560_SoPW.pl Evaluating Test Condition: $cTestH{$dbFile}{$timeRng}{$regionName}{A}& +!$cTestH{$dbFile}{$timeRng}{$regionName}{B}&!$cTestH{$dbFile}{$timeRn +g}{$regionName}{C}... Result is: 1 12:55 >

      Hope that helps,

      Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Perl Boolean Evaluation Shows Incorrect Results
by dsheroh (Monsignor) on Mar 01, 2016 at 08:44 UTC
    Aside from the escaping issue that Tanktalus pointed out, I suspect that you actually meant to use && (boolean and) rather than & (bitwise and). In this particular case, they happen to be equivalent, but, if your code ever needs to deal with values other than 1 and 0, using bitwise operators when you intend to perform boolean operations can produce unexpected results:
    $ perl -E 'say 1 & 2 & 3' 0