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

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

I am trying to stop the execution of code when an error is found. I have "error" subroutines for example.

sub lam_num_error { $mw->messageBox(-message=>"The input must be an integer."); exit; }

The exit command is exiting the program completely which is not what I want. I've also tried this.

sub lam_num_error { $mw->messageBox(-message=>"The input must be an integer."); die; }

Using die seems to stop the execution of code but still keep the main window on the screen, which is what I want. However, I'm getting some errors like this.

Tk::Error: Died at Fastenator_working.pl line 1106. main::fl_num_error at Fastenator_working.pl line 1106 main::calc_fast_loads at Fastenator_working.pl line 1096 main::run_button at Fastenator_working.pl line 815 Tk callback for .frame13.button Tk::__ANON__ at C:/MSC.Software/Patran/2008_r2/Perl_msc/site/lib/Tk.p +m line 247 Tk::Button::butUp at C:/MSC.Software/Patran/2008_r2/Perl_msc/site/lib +/Tk/Button .pm line 111 <ButtonRelease-1> (command bound to event)

I'm not comfortable with these errors even though the code is still doing what I want. Can someone explain this and possibly suggest the best way to achieve my goal? I want the code to stop, let the user make some modifications to the input in the main window and then try again without completely shutting down the program. Thank you in advance!

Replies are listed 'Best First'.
Re: Die vs. Exit
by davido (Cardinal) on Jul 20, 2012 at 20:34 UTC

    Use exit to exit your script. Use die to thrown an exception. Exceptions can be trapped. Exceptions that are not trapped will result in the script terminating with a message. While it's not common practice to do so, one could even call exit after catching a thrown exception that cannot be handled gracefully (it's more common just to re-throw the exception so that possibly some higher layer might still be able to recover).

    Use die in situations where you are reacting to an exceptional event. If it's possible to prevent a non-integer from finding its way into your script so that you never end up in an error state, that can often be desirable. But if it's impractical to prevent bad input, then throwing an exception might be the way to handle it. However, using eval or Try::Tiny, you can catch the exception at some other level and handle it more gracefully (close the windows, and then exit(1), for example. Or reset to an earlier state and prompt again for input.).


    Dave

      This little bit of code might help. In the bigger picture, you probably shouldn't be calling die or exit, just to catch bad user input, use validation rountines on Entrys, etc.
      #!/usr/bin/perl use warnings; use strict; use Tk; require Tk::ErrorDialog; my $mw = new MainWindow; $mw->title("Close test"); $mw->geometry("400x250"); #prevents mw from closing $mw->protocol('WM_DELETE_WINDOW' => \&save_it ); $mw->after(2000, sub{ die } ); MainLoop; sub save_it { print "do stuff here before the exit\n"; $mw->messageBox(-message=>"you tried to exit!"); }

      I'm not really a human, but I play one on earth.
      Old Perl Programmer Haiku ................... flash japh
Re: Die vs. Exit
by mbethke (Hermit) on Jul 20, 2012 at 20:05 UTC

    Both die and exit usually stop execution of the entire program, the difference being that die can be caught in an eval and thus serve as an exception mechanism. You likely want neither of these. All you have to do is exit your current callback with return after creating the message box. When you create it you can give it a callback for the confirmation button that clears the input field with the wrong data and puts the focus on it so the user immediately knows where to retry.

    Sorry for not providing any code here, it's been over a decade since I last used Perl/Tk and I'd have to look up all the API again. Hope it helps anyway.

Re: Die vs. Exit
by kcott (Archbishop) on Jul 20, 2012 at 21:54 UTC
    I want the code to stop, let the user make some modifications to the input in the main window and then try again without completely shutting down the program.

    Here's a piece of working code that does just that:

    #!/usr/bin/env perl use strict; use warnings; use Tk; my $mw = MainWindow->new(); $mw->Label(-text => 'Enter integers only:')->pack; $mw->Entry( -validate => 'key', -validatecommand => sub { $_[0] =~ /^\d+$/ }, -invalidcommand => \&lam_num_error, )->pack; $mw->Button(-text => 'Exit', -command => sub { exit })->pack; MainLoop; sub lam_num_error { $mw->messageBox(-message=>"The input must be an integer."); }

    This is very basic and is only intended to show an example of Tk::Entry Validation. As it is, it only allows positive integers: you may want to change that.

    Note that there's no die or exit in lam_num_error(). An Exit button is provided for users to quit the application.

    -- Ken

      This is an excellent example - exactly what I'm try to do! Thank you very much!

        I'm having trouble figuring out the regular expression for integers, positive or negative?

        /^-?\d+$/

        Can someone please explain what the characters mean? I may have better luck figuring it out with a good explanation? Thanks!

Re: Die vs. Exit
by aitap (Curate) on Jul 20, 2012 at 20:13 UTC
    In addition to the previous post: Tk::Error is called there. You can catch some errors using this method.
    Sorry if my advice was wrong.
Re: Die vs. Exit
by Anonymous Monk on Jul 21, 2012 at 03:15 UTC
    A really good way to handle a lot of things is to put an exception-catching statement around every, say, user-interface driven section of your program. Anywhere within that section, the logic can throw an exception by means of die, and, no matter where it is when it does so, control will immediately pass to the (innermost) exception handler. Notice that die can throw strings or objects. You could, for example, display a dialog-box containing the text of an error-string that was part of the exception that was caught. The logic of the program is simplified because, "if you made it to the end, then it worked." And, "if you made it to the exception handler, it didn't work." It doesn't matter how deep-down in the logic of the application you were when you threw the exception: poof... you are now in the exception handler.