[Prepended This is a failure story. In the spirit of the statement "You learn from your mistakes" I figured you might be able to learn from my mistake and avoid making it yourself. (and learn that B::Deparse is a great diagnostic tool).]

I wasted a lot of time this weekend when a seemingly correct grep() expression didn't work. A few modifications later and I had something that appeared to work correctly (but had a hidden bug). Eventually I asked for assistance and pfaut suggested that I look at perl's interpretation of my code by using B::Deparse on the script (perl -MO=Deparse filename.pl). This immediately revealed the problem with my original construction and also a serious bug in the expression that appeared to work. I've corrected the bug and I think its interesting enough to share with all of you.

@fks = grep { not $_->table_to->name eq $orig_fk->table_from->name and $col->eq([$orig_fk->columns_from], [$_->columns_to]) } @fks; # After B::Deparse @fks = grep { if (! $_->table_to->name eq $orig_fk->table_from->name) { $col_eq->([$orig_fk->columns_from], [$_->columns_to); } } @fks;

not( expr ) and expr: This details that the not() is associated only with the first expression and the second expression doesn't affect the overall result of the grep expression. The net effect was to always return false. This is what prompted me to look into the problem in the first place.

@fks = grep { my $r = not $_->table_to->name eq $orig_fk->table_from->name and $col->eq([$orig_fk->columns_from], [$_->columns_to]) $r; } @fks; # After B::Deparse @fks = grep { if (my $r = ! $_->table_to->name eq $orig_fk->table_from->name) { # Note that $r isn't being written to $col_eq->([$orig_fk->columns_from], [$_->columns_to); } $r; } @fks;

($r = not expr) and expr; $r: This details that while my expectation that $r would contain the result of the aggregate expression it really wasn't. It appeared to work because the first expression caught all the cases my data was presenting. The second expression still doesn't affect the overal result but I wouldn't know this until much later. This is the second and critical bug that B::Deparse highlighted for me.

@fks = grep not( $_->table_to->name eq $orig_fk->table_from->name and $col->eq([$orig_fk->columns_from], [$_->columns_to]) ), @fks; # OR @fks = grep not $_->table_to->name eq $orig_fk->table_from->name && $col->eq([$orig_fk->columns_from], [$_->columns_to]), @fks;

not( expr and expr ): This is how I should have written it. The first example requires parentheses after not() and wrapping both expressions to override the default precedence. The second is correct without parentheses but is uglier because it uses the && operator.

So... a long while later this is an object lesson in what happens when you neglect your precedence. I've gotten very used to the and and or operators' and not's higher precedence just threw me for a loop.

Anyone who wants to review perl's precedence should review perlop


In reply to How not to use not() by diotalevi

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.