http://www.perlmonks.org?node_id=136951


in reply to How to build a real multi-level dispatch table
in thread Why I Hate Nested If-Else blocks

I've been following this thread with some interest, as I just finished writing a CGI with a very unwieldy set of if / elsif / else statements, and I'm interested in how to put it on a more rational footing (posted below for anyone who wants a laugh). In simpler situations I've used a dispatch table. But here I couldn't work out how to pass (the right) arguments. As far as I can see, this is not handled explicitly above. I'd be interested in how to deal with the need (A) to pass different arguments to different subs; and (B)to pass different args to the *same* sub under different conditions ?

My baobab-style if tree, so we can all see what I'm up against:
if ($g{'Action'} eq 'MainPage') { MainPage($Persist, $UserName); } if (($g{'Action'} eq 'Course') or ($g{'Action'} eq 'EditCourse')) +{ $g{'CourseID'} = GetNewCourse() unless defined $g{'CourseID'}; UpdateTempData($g{'CourseID'}); EditCourse($Persist, $g{'CourseID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'Create Course') { my $CourseID = GetNewCourse($UserName); UpdateTempData($CourseID); EditCourse($Persist, $CourseID, $g{'Return'}); } elsif ($g{'Action'} eq 'EditEvent') { EditEvent($Persist, $g{'CourseID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'New Venue') { my $VenueID = GetNewVenue($Persist,$UserName); EditVenue($Persist, $VenueID, $g{'Return'}); } elsif (($g{'Action'} eq 'Venue') or ($g{'Action'} eq 'EditVenue')) + { EditVenue($Persist, $g{'VenueID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'Course Overview') { CourseView($Persist, $UserName); } elsif ($g{'Action'} eq 'Venue Overview') { VenueView($Persist,$UserName); } elsif ($g{'Action'} eq 'DeleteCourse') { DeleteCourse($Persist, $g{'CourseID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'Delete Course') { DeleteCourseYes($Persist, $g{'CourseID'}, $g{'Return'}); if ($g{'Return'} eq 'CourseView') { CourseView($Persist, $UserName); } else { MainPage($Persist, $UserName); } } elsif ($g{'Action'} eq 'Keep Course') { if ($g{'Return'} eq 'CourseView') { CourseView($Persist, $UserName); } else { MainPage($Persist, $UserName); } } elsif ($g{'Action'} eq 'DeleteEvent') { DeleteEvent( $Persist, $g{'EventID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'Delete Event') { DeleteEventYes( $Persist, $g{'EventID'}); if ($g{'Return'} eq 'CourseView') { CourseView($Persist, $UserName); } elsif ($g{'Return'} eq 'EditEvent') { EditEvent($Persist, $g{'CourseID'},0,$g{'CourseTitle'}); } else { MainPage($Persist, $UserName); } } elsif ($g{'Action'} eq 'Keep Event') { if ($g{'Return'} eq 'CourseView') { CourseView($Persist, $UserName); } elsif ($g{'Return'} eq 'EditEvent') { EditEvent($Persist, $g{'CourseID'},0,$g{'CourseTitle'}); } else { MainPage($Persist, $UserName); } } elsif ($g{'Action'} eq 'DeleteVenue') { DeleteVenue($Persist, $g{'VenueID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'Delete Venue') { DeleteVenueYes($Persist, $g{'VenueID'}, $g{'Return'}); if ($g{'Return'} eq 'VenueView') { VenueView($Persist, $UserName); } else { MainPage($Persist, $UserName); } } elsif ($g{'Action'} eq 'Keep Venue') { if ($g{'Return'} eq 'VenueView') { VenueView($Persist, $UserName); } else { MainPage($Persist, $UserName); } } elsif ($g{'Action'} eq 'Save Venue') { if (my $Errors = SaveVenue($Persist, $UserName)) { EditVenue($Persist, $g{'VenueID'}, $g{'Return'}, $Errors); } else { WriteVenue(); if ($g{'Return'} eq 'ReturnToEditEvent') { SaveVenue($Persist, $UserName); EditEvent($Persist, $g{'CourseID'}, $g{'Return'},$g{'C +ourseTitle'},0); } elsif ($g{'Return'} eq 'VenueView') { SaveVenue($Persist, $UserName); VenueView($Persist, $UserName); } else { SaveVenue($Persist, $UserName); MainPage($Persist, $UserName); } } } elsif ($g{'Action'} eq 'More Keywords') { EditCourse($Persist, $g{'CourseID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'Next Step') { if (my @Errors = CourseErrorCheck()) { EditCourse($Persist, $g{'CourseID'}, $g{'Return'}, \@Error +s); } elsif (my $OldTitle = TitleCheck()) { UpdateTempData($g{'CourseID'}); QueryTitle($Persist, $g{'CourseID'}, $g{'Return'}, $OldTit +le); } else { UpdateTempData($g{'CourseID'}); EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'}); } } elsif ($g{'Action'} eq 'New Course') { my $g = GetFromFile($g{'CourseID'},\%g); %g = %$g; DestroyTempFile($g{'CourseID'}); $g{'CourseID'} = GetNewCourse(); MakeTempFile($g{'CourseID'}); UpdateTempData($g{'CourseID'}); EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'Change Name') { UpdateTempData($g{'CourseID'}); EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'More Links') { UpdateTempData($g{'CourseID'}); EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'}); } elsif ($g{'Action'} eq 'Another Page') { SaveUserPage($Persist, $g{'CourseID'},$g{'PageTitle'},$g{'Page +Text'},$g{'WeFormat'},$g{'CurrentPage'}); $g{'PageTitle'} = undef; $g{'PageText'} = undef; EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'},0,1); } elsif ($g{'Action'} =~ /^Edit Page (\d*)$/) { SaveUserPage($Persist, $g{'CourseID'},$g{'PageTitle'},$g{'Page +Text'},$g{'WeFormat'},$g{'CurrentPage'}); EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'}, $g{"Pag +eID_$1"},1); } elsif ($g{'Action'} =~ /^Delete Page (\d*)$/) { UpdateTempData($g{'CourseID'}); SaveUserPage($Persist, $g{'CourseID'},$g{'PageTitle'},$g{'Page +Text'},$g{'WeFormat'},$g{'CurrentPage'}); QueryDeleteUserPage($Persist, $g{'CourseID'}, $g{'Return'},$g{ +"PageID_$1"},$g{'CurrentPage'}); } elsif ($g{'Action'} eq 'Yes, Delete Page') { DeleteUserPage($g{'PageID'}); UpdateTempData($g{'CourseID'}); EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'},$g{'Curr +entPage'},1); } elsif ($g{'Action'} eq 'No, Keep Page') { UpdateTempData($g{'CourseID'}); EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'},$g{'Curr +entPage'},1); } elsif ($g{'Action'} eq 'No, Keep Page') { UpdateTempData($g{'CourseID'}); EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'},$g{'Curr +entPage'},1); } elsif ($g{'Action'} eq 'Proceed') { SaveUserPage($Persist, $g{'CourseID'},$g{'PageTitle'},$g{'Page +Text'},$g{'WeFormat'},$g{'CurrentPage'}); UpdateTempData($g{'CourseID'}); if (my $TearSheetError = CourseInfoErrorCheck()) { EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'},0,0, +$TearSheetError); } else { EditEvent($Persist, $g{'CourseID'}, $g{'Return'},$g{'Cours +eTitle'},0); } } elsif ($g{'Action'} eq 'Save Course') { SaveUserPage($Persist, $g{'CourseID'},$g{'PageTitle'},$g{'Page +Text'},$g{'WeFormat'},$g{'CurrentPage'}); UpdateTempData($g{'CourseID'}); if (my $TearSheetError = CourseInfoErrorCheck()) { EditCourseInfo($Persist, $g{'CourseID'}, $g{'Return'},0,0, +$TearSheetError); } else { SaveCourse($Persist, $g{'CourseID'}, $g{'Return'}); if ($g{'Return'} eq 'CourseView') { CourseView($Persist, $UserName); } else { MainPage($Persist, $UserName); } } } elsif ($g{'Action'} eq 'Make Venue') { my $VenueID = GetNewVenue($Persist,$UserName); EditVenue($Persist, $VenueID,'ReturnToEditEvent',0,$g{'CourseI +D'},$g{'CourseTitle'}); } elsif ($g{'Action'} eq 'Add Event') { if (my $Errors = CheckEvent($g{'CourseID'})) { EditEvent($Persist, $g{'CourseID'}, $g{'Return'},$g{'Cours +eTitle'},$Errors); } else { AddEvent($Persist, $g{'CourseID'}, $g{'CourseTitle'}); EditEvent($Persist, $g{'CourseID'}, $g{'Return'},$g{'Cours +eTitle'},0); } } elsif ($g{'Action'} eq 'Save All') { my $Errors = CheckEvent($g{'CourseID'}); my $DateError = 0; my $VenueError = 0; my $DuplicateError = 0; if ($Errors) { $DateError = 1 if grep {$_ eq 'Date'} @$Errors; $VenueError = 1 if grep {$_ eq 'Venue'} @$Errors; $DuplicateError = 1 if grep {$_ eq 'Duplicate'} @$Errors; } if ($DateError + $VenueError == 1) { EditEvent($Persist, $g{'CourseID'}, $g{'Return'},$g{'Cours +eTitle'},$Errors); } else { AddEvent($Persist, $g{'CourseID'}, $g{'CourseTitle'}) unle +ss ($DuplicateError == 1 or $DateError + $VenueError == 2); if (stat "$filepath/tempfiles/$g{'CourseID'}") { UpdateTempData($g{'CourseID'}); SaveCourse($Persist, $g{'CourseID'}, $g{'Return'}); } if (defined $g{'Return'} and $g{'Return'} eq 'CourseView') + { CourseView($Persist, $UserName); } else { MainPage($Persist, $UserName); } } } else { MainPage($Persist, $UserName, $UserCookie); }


§ George Sherston

Replies are listed 'Best First'.
(tye)Re: How to build a real multi-level dispatch table
by tye (Sage) on Jan 08, 2002 at 02:00 UTC

    That is what closures are for:

    my %actions= ( MainPage => sub { MainPage( $Persis, $UserName ) }, Course => sub { EditCourse( $Persist, def(\$g{CourseID},sub{GetNewCourse()}), $g{Return} ) }, EditCourse => 'Course', 'Create Course' => sub { EditCourse( $Persist, GetNewCourse($UserName), $g{Return} ) }, EditEvent => sub { EditEvent( $Persist, $g{CourseID}, $g{Return} ) }, 'New Venue' => sub { EditVenue( $Persist, GetNewVenue($Persist,$UserName), $g{Return} ) }, Venue => sub { EditVenue( $Persist, $g{'VenueID'}, $g{'Return'} ) }, EditVenue => 'Venue', 'Delete Course' => \&DeleteCoursePage, 'Keep Course' => sub { if ($g{'Return'} eq 'CourseView') { CourseView($Persist, $UserName); } else { MainPage($Persist, $UserName); } }, # ... ); # ... my $action= $actions{ $g{Action} }; if( ! $action ) { MainPage( $Persist, $UserName, $UserCookie ); } else { $action= $actions{$action} if ! ref($action); $action->(); }
    where you add more subroutines as needed to keep the hash declaration from being too complex.

            - tye (but my friends call me "Tye")