Gossamer Forum
Home : Products : Gossamer Links : Version 1.x :

Minor print_cat logic bug

Quote Reply
Minor print_cat logic bug
Minor logic formatting bug in the print_cat routine:

I don't know if this is in the 'stock' routine, or if it's been created
by all the various versions, but it affects formatting of tables/columns.

If you use several levels of nested tables, getting them to format properly
is sometimes aesthetically difficult.

To that end, I added a 'wdith' tag to the column parameters of the print_cat,
but that didn't solve everything, in fact, it showed another bug.

First, add the following to the top of the routine:


my $width = int (100 / $LINKS{build_category_columns}) ;
$width = 'width=' . $width .'%';

Then, where the start table code is, add $width to the string:


$output = qq|<div class="margin"><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="catlist" $width valign="top">\n
|;

When you hit the following code, you see the bug. $i starts out as 0. That
is always false. It forces the second part of the main clause to print, and
you end up with a second column. You want to check if $i is _not_ 0 -- if it
is zero, just fall through. (ie: !$i if $i is zero is "TRUE")


# We check to see if we are half way through, if so we stop this table cell
# and begin a new one (this lets us have category names in two columns).
(!$i or ($i % $breakpoint)) or ($output .= qq|</td><td class="catlist" $width valign="top">\n|);
$i++;



The "bug" is the part:
($i and ($i % $breakpoint)) or ($output .= qq|</td><td class="catlist" valign="top">\n|);

What happens, is if $i is 0,the first part of the whole expression evaluates to "false" so the second part of the 'or' is done -- ie: an empty column is printed out.

The logic is ugly.... but the modified version works with complicated nested tables, while the original version doesn't --. My $width mod, allows the columns to be the same size, rather than randomly formatted.

I hate logic, it's so unforgiving!

PUGDOGŪ
PUGDOGŪ Enterprises, Inc.
FAQ: http://postcards.com/FAQ


Quote Reply
Re: Minor print_cat logic bug In reply to
Which version are you referring to? It really helps to post the Version, since v.1.11, v.1.12, v.1.13, and the NG version are floating around in cyberspace.

Regards,

Eliot Lee
Quote Reply
Re: Minor print_cat logic bug In reply to
Well, it looks like it's the 1.1x series.

All the copies I have required the change.

I don't know if it's in the NG version or not... but the print_cat routine didn't look that much different when I eyeballed it.

Here's the part of the routine from the NG code:

Code:
# We check to see if we are half way through, if so we stop this table cell
# and begin a new one (this lets us have category names in two columns).
($i > 0) and !($i % $breakpoint) and ($output .= qq|</td>\n<td valign="top" class="catlist">\n|);
$i++;
$output .= Links::load_template ('subcategory.html', $cat_r, 0);
}
As you can see, the logic was reversed, and is still about as obscure <G>

This at least is readable left to right:

If $i greater then 0, AND the result of integer division is NOT NOT ZERO, then start a new column.

That way, if $i is 0 (the first iteration) the AND tests fail, then, on subsequent iterations, you are checking for !($i % $breakpoint) which is "if the remainder of an integer division is NOT ZERO" then fail the test, and add the value, otherwise, it's TRUE (if the $i % $breakpoint is 0, !0 is TRUE), check the next "AND" which is simply 'do something' which always is evaluated.

<whew!>

I think I explained that right!

Basically, each clause of the statement to the right of an 'and' is only evaluated _IF_ the statements to the LEFT of it are all TRUE (since an 'and' can't be TRUE if any one of the statements is FALSE, the compiler saves some time by stopping as soon as any part of the logic test in left to right, order of precicence evaluation, fails).


'or' statements are evaluated until the FIRST 'TRUE' is found, then not evaluated any further, so an 'or' is often used as an "if" type test, in the negative.

ex: ($some_value) or exit;

If $some_value is true, the entire statement is true, so the exit' is never evaluated. If the $some_value is false, the exit; is evaluated.

These take a real while to get used to, but once you get used to them, there are some situations where they _really_ can make things clearer, by not using nested if loops, as long as you are careful. AND --- you chose the times you use it carefully. Overdoing it can make unreadable and unexplainable code, since in 'binary' (logic) one misread somewhere in the statement, changes everything further down.

multiple 'and's can be used as if statements in the positive...

ex: ($some_value) and ($another_value) and ($more_conditions) and "do something"

The problem comes in if you put an "or" in somewhere... since "and" has higher precedence, you need to use proper nesting ()

ex:
($some_value) and ($another_value) and ($more_conditions) or "do something"

would be the opposite of the first statement. the "do something" is evaluated if any of the "ands" ring false, in left to right order.

It gets tricky if you do something like:

($some_value) and ($another_value) or ($more_conditions) and "do something"

<G>

I leave that to you all to figure out :)

this is _NOT_ something you really want to write without parenthesis. you'll never debug it, or really even figure out what was on the person's mind who wrote it, without looking at the rest of the whole routine in reverse.

Ouch!



PUGDOGŪ
PUGDOGŪ Enterprises, Inc.
FAQ: http://postcards.com/FAQ