Roll Your Own
Try to Handle This
I’m back! I apologize to all of my readers for the lengthy hiatus that I have had to take from writing this column. It’s been an unbelievably busy couple of months: I started a new job for The Support Group as a developer for their new Los Angeles office, and at the moment my home is piled high with boxes as we prepare to move. I’m glad to be back though, as it means we can continue our journey through the wonderful world of programming.
While I have it in my mind to do so, I want to thank all of you out there who have e-mailed to let me know that you’re enjoying this series. A number of you have asked that I show examples of integrating AppleScript with other programs such as FileMaker Pro. While I may get into using AppleScript with scriptable programs eventually, for the time being I’m concentrating on how to think about programming in general and how to create programs that do what you want them to do using only AppleScript and the standard additions included with the Mac OS. As this is a Mac e-zine, I can be pretty sure that everyone has AppleScript, but not everyone has FileMaker Pro (even though they should, as it’s a great database management program).
• • •
This month we’re going to take a look at error checking in general and AppleScript’s try
block in particular. As we’ve seen before, sometimes things don’t work out as we plan in our programs. We’ve been building a simple program that will prompt the user to enter a number and will sum up all the integers up to that number. For reference, here’s the program we left in the last column.
-- Get the number to sum up to from the user. display dialog "Please enter a positive number:" default answer ¬ "" buttons {"OK"} default button 1 -- Get the data entered by the user into the dialog's field set theNumber to the text returned of result -- Assume that invalid data was entered set isValidEntry to false -- Repeat the following block of statements until we've made -- sure that the user has entered valid data. repeat until isValidEntry -- Attempt to coerse the data entered by the user into a number. try -- If a non-numeric entry was made by the user the -- following statement will produce an error. set theNumber to theNumber as number -- If the data entered by the user is a number but -- isn't an integer, manually produce an error. if class of theNumber is not integer then error -- If no error was produced, set the isValidEntry -- variable to true so that we can exit the loop. set isValidEntry to true on error -- If an error was produced, alert the user and ask for -- valid data. display dialog "That is not a valid entry. " & ¬ "Please enter a positive integer:" default answer ¬ "" buttons {"OK"} default button 1 -- Get the data entered by the user. set theNumber to text returned of result end try -- set theNumber to theNumber as number end repeat -- until isValidEntry -- Initialize sum to 0. set sum to 0 -- Sum up the numbers. repeat with i from 1 to theNumber set sum to sum + i end repeat -- with i from 1 to theNumber -- Report the results of the process to the user. display dialog "The sum of the first " & theNumber & " ¬ numbers is " & sum & ¬ "." buttons {"OK"} default button 1
As you can see, this code already has a try
block in it, which attempts to capture an error that could happen. Specifically, if the user enters text or if the user enters a number that isn’t an integer, then we try to handle it elegantly instead of letting the program behave improperly.
This is a specific example of the general idea behind error checking. When writing software, one of the things the programmer has to thing about is what could go wrong, and account for that possibility. In our summing program, one possible problem is that the user can enter anything into the dialog box, but only positive integers make sense to the program.
If we simply try to execute the program without the try
block, the program will choke if the user enters text information such as “ten” or if the user enters a number with a fractional part.
As an example, here’s a version of the program that doesn’t do any error checking:
-- Get the number to sum up to from the user. display dialog "Please enter a positive number:" default answer ¬ "" buttons {"OK"} default button 1 -- Get the data entered by the user into the dialog's field set theNumber to the text returned of result -- Assume that invalid data was entered set isValidEntry to false -- Initialize sum to 0. set sum to 0 -- Sum up the numbers. repeat with i from 1 to theNumber set sum to sum + i end repeat -- with i from 1 to theNumber -- Report the results of the process to the user. display dialog "The sum of the first " & theNumber & ¬ " numbers is " & sum & ¬ "." buttons {"OK"} default button 1
If you run this program and enter “ten” into the dialog box, you’ll get an error message that says “Execution Error, Can’t make ‘ten’ into a integer.,” and the program will terminate. If the user enters a number with a fractional part, a similar error message will appear. Basically, the program can’t handle the input, and computers are stupid, so it gives up.
Notice how much shorter the version without error checking is. As you can see, it’s much easier to write a program without error checking than with, but that makes the experience harder on your users. Making things easier for the user usually is more difficult for the programmer, but it’s worth it; it’s your job, as the programmer, to anticipate these problems, and fortunately AppleScript gives us that try
handler to help us out.
Enclosing AppleScript code within a try
block will tell AppleScript to not choke if there’s a problem, but to instead jump to the on error
handler, which can take care of the problem gracefully. The on error
handler of our program simply reports to the user that what he entered wasn’t valid, and gives him instructions as to what a valid entry is.
The summing program can enter the on error
handler in two ways. The first is by attempting to coerced what the user entered into a number with the code set theNumber to theNumber as number
. If the user enters “ten,” which can’t be coerced into being a number, then the error is produced and execution continues at the beginning of the on error
handler.
The second way to enter the on error
handler is by actually calling an error manually, which we do if the class of theNumber
isn’t an integer. error
is actually a command that you can use to manually produce an error.
Whenever an error is produced in AppleScript it is accompanied by an error message and an error number. In our current version of the program, we ignore these pieces of information, but they can be useful since more than one error might happen within a try block and we might wish to do different things depending on the error produced.
Here’s a rewrite of our program that tracks the error number and gives the user more useful feedback as to the nature of the problem.
-- Get the number to sum up to from the user. display dialog "Please enter a positive number:" default answer ¬ "" buttons {"OK"} default button 1 -- Get the data entered by the user into the dialog's field set theNumber to the text returned of result -- Assume that invalid data was entered set isValidEntry to false -- Repeat the following block of statements until we've made -- sure that the user has entered valid data. repeat until isValidEntry -- Attempt to coerse the data entered by the user into a number. try -- If a non-numeric entry was made by the user the -- following statement will produce an error. set theNumber to theNumber as number -- If the data entered by the user is a number but -- isn't an integer, manually produce an error. if class of theNumber is not integer then error number 500 -- If no error was produced, set the isValidEntry -- variable to true so that we can exit the loop. set isValidEntry to true on error number errNum -- Use the errNum to determine what went wrong. if errNum is equal to -1700 then set dialogMessage to "You entered text instead of a number." else if errNum is equal to 500 then set dialogMessage to "You have entered a number with a fractional part." end if -- If an error was produced, alert the user and ask for -- valid data. display dialog dialogMessage & ¬ " Please enter a positive integer:" default answer ¬ "" buttons {"OK"} default button 1 -- Get the data entered by the user. set theNumber to text returned of result end try -- set theNumber to theNumber as number end repeat -- until isValidEntry -- Initialize sum to 0. set sum to 0 -- Sum up the numbers. repeat with i from 1 to theNumber set sum to sum + i end repeat -- with i from 1 to theNumber -- Report the results of the process to the user. display dialog "The sum of the first " & theNumber & ¬ " numbers is " & sum & "." buttons {"OK"} default button 1
In the first error possible, where the user enters text instead of a number, AppleScript produces an error -1700, which means that it can’t condense the text into a number. In the second error, we produce an error number 500. We used the number 500 because it doesn’t interfere with any error number produced by AppleScript. In general, when calling the error handler manually, you can use numbers ranging from 500 to 10000.
Once we’ve entered the error handler, we’ve captured the error number in the variable errNum
. We could have also captured the error message by changing the on error
line to read on error
errMsg number errNum
. This would have set the variable errMsg
to the message that the error produced. We could have then called it manually with error "Can't sum fractional numbers" number 500
and when the error handler was entered by that line, the errMsg
variable would have contained the text Can't sum fractional numbers
. Feel free to try out these changes and add a display dialog
line within the on error
handler.
Since we now know why the error handler was entered, we can customize our message to the user to give more complete feedback and let her know what went wrong. We store this custom message in a new variable called dialogMessage
and use that as part of the text displayed in the display dialog
line.
• • •
Now you understand how to check for problems that the user might create with your program and how to handle the problems gracefully. Here’s your exercise for the month: What other errors might happen based on what the user enters? Re-write the program to account for these errors. I can think of at least one other error the program should account for, and I’ll include that possibility in the program next month. Perhaps you’ll see it too, or perhaps you’ll see a potential problem that I don’t.
The on error
handler is a special kind of handler that is part of the AppleScript language, but the AppleScript language allows us to create our own handlers. We’ll cover what that means and how to do it next month. Until then, happy programming!
Also in This Series
- Getting the List of It—Part 2 · July 2003
- Getting the List of It · June 2003
- The Object of Programming—Part 2 · March 2003
- The Object of Programming · February 2003
- How to Handle Anything · January 2003
- Try to Handle This · December 2002
- Charting Your Success · September 2002
- Go with the Flow · August 2002
- Variables and Data · June 2002
- The Ultimate Customization · May 2002
- Complete Archive
Reader Comments (1)
Add A Comment