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

I've been looking at this code for a few days now, the simplicity is insane, yet I cannot find where the code is broken.
my $counter = 0; my %user_ranges = (); my $julian_day = 0; for my $date ($beginning_date..$ending_date) { # run through the main +range and create smaller ranges my ($year, $month, $day) = ((substr $date, 0, 4),(substr $date, 4, 2 +),(substr $date, 6, 2)); next if !check_date ($year, $month, $day); # next iteration if date + is not valid print "passed as a vaild day: $year$month$day<br>"; # next iteration if the weekday range is selected and the date is no +t on a weekday next if (((Day_of_Week ($year, $month, $day)) > 5) && ($session_vars +{'date_type'} == 2)); print "passed as a weekday: $year$month$day<br>" if ($session_vars{'da +te_type'} == 2); # next iteration if the weekend range is selected and the date is no +t on a weekend next if (((Day_of_Week ($year, $month, $day)) < 6) && ($session_vars +{'date_type'} == 3)); print "passed as a weekend: $year$month$day<br>" if ($session_vars{'da +te_type'} == 3); if (($julian_day + 1) == (Day_of_Year ($year, $month, $day))) { #one day later $user_ranges{$counter}->[1] = $date; print "assigned $date as end date to range # $counter<br>"; $julian_day++; print "same range: julian day-$julian_day -- counter-$counter -- d +ate: $date<br>"; } else { # this is where the problem lies, notice '$counter >= 1' used to read +!$counter if ((!$user_ranges{$counter}->[1]) && ($counter >= 1)) { # if rang +e is one day long print "\n\ncounter: $counter -- user ranges 0: $user_ranges{$counter}- +>[0] -- user ranges 1: $user_ranges{$counter}->[1]<br>"; $user_ranges{$counter}->[1] = $user_ranges{$counter}->[0]; } #range switch $counter++; $user_ranges{$counter}->[0] = $date; print "assigned $date as beginning date to range # $counter<br>"; $julian_day = Day_of_Year ($year, $month, $day); print "new range: julian day-$julian_day -- counter-$counter -- da +te: $date<br>"; } }
This code uses Date::Calc and the $beginning_date and $ending_date are in the form: 20030218 (year, month, day).

What happens, is where the conditional tests to see if a date range is a singular day and assigns the ending date to be the same as the beginning date. If I comment out the if statement completely, the code works as expected. The $user_ranges hash is populated correctly. If I uncomment the if statement, I get an erroneous entry in the %user_ranges hash. $user_ranges{0}->[0] = 0; Based on the fact that $counter is never 0 (only on assignment) I don't understand where this could be assigned.

The many print statements are my attempt to trace the variables' values. The print statement inside the offending contitional never prints (in most instances, only if the expression becomes true) yet only if this code is in use do I get a 0 key in the %user_ranges hash. Nowhere else are these values modified.
BlackJudas

20030326 Edit by Corion: Changed (8-space) tabs to 2 spaces

Replies are listed 'Best First'.
Re: Imaginary Key
by Enlil (Parson) on Mar 25, 2003 at 03:14 UTC
    I think that if you were to change this line:
    if ((!$user_ranges{$counter}->[1]) && ($counter >= 1)){ # if range is +one day long
    to this:
    if ( ($counter >= 1) && (!$user_ranges{$counter}->[1])) { # if range i +s one day long
    the problem seems to go away (i believe it is autovivification that is causing the error).

    -enlil

      Thank you Enlil for actually trying to compile the code :). I still cannot see why perl would autovivificate that hash in a conditional. I've got to look at it more closely.
      BlackJudas