I am trying to end a script upon clicking “quit”… I am not sure of what the best way to do this is, but right now-- If I click “ok” when the answer is not an integer, and am given the alert “you must enter a number”, and then click quit, it will take me back to where I was previously, because it’s returning back from the previous method call…
So the question is-- is there a way to pop the stack? Or is there an entirely better way to do this sort of thing?
Thank you.
-patrick
my do_something()
on do_something()
set question to (display dialog "enter a number:" default answer "" buttons {"Ok", "Quit"} default button 1)
set button to button returned of question
if button = "Quit" then return
try
-- "" can be convertedd to integer
if x = "" then x = "a"
set x to text returned of question as integer
on error
display dialog "Answer must be a number!" buttons {"Ok"} default button 1
my do_something()
end try
display dialog "did I get here?"
end do_something
I generally recommend not calling a handler from within itself and in this instance you don’t even need a handler although you could certainly use one. Here is an example just using a repeat rather than a handler.
set exitLoop to false
repeat until exitLoop is true
set {button, x} to {button returned, text returned} of (display dialog "enter a number:" default answer "" buttons {"Ok", "Quit"} default button 1 cancel button 2)
try
-- "" can be convertedd to integer
if x = "" then set x to "a"
x as integer
set exitLoop to true
on error
display dialog "Answer must be a number!" buttons {"Ok"} default button 1
end try
end repeat
display dialog "did I get here?"
repeat
display dialog "Enter a number:" default answer ""
set x to text returned of result
try
if x is "" then error
set x to x as integer
exit repeat
on error
display dialog "Answer must be a number!" buttons {"OK"} default button 1
end try
end repeat
Or even a slight change to your version, Patrick:
my do_something()
on do_something()
display dialog "enter a number:" default answer "" buttons {"Ok", "Quit"} default button 1 cancel button 2
set x to text returned of result
try
-- "" can be convertedd to integer
if x = "" then x = "a"
set x to x as integer
on error
display dialog "Answer must be a number!" buttons {"Ok"} default button 1
my do_something()
end try
display dialog "did I get here?"
end do_something
Ok, so now I am curious-- This is the actual context of what my script is doing. Do you guys still advise that I don’t do this with calling handlers within handlers? What would be an alternate way to structure this with repeats?
Thanks…
-patrick
my start_program()
on start_program()
set a to random number from 1 to 10
set b to random number from 10 to 99
set c to {"times", "plus", "minus"}
set type to item ((random number (count c) - 1) + 1) of c
my generate_question(a, b, c, type)
end start_program
on generate_question(a, b, c, type)
set my_dialog to "Hey, What is " & (a as string) & " " & type & " " & (b as string) & "?"
if type = "plus" then
set answer to a + b
else if type = "minus" then
set answer to a - b
else if type = "times" then
set answer to a * b
end if
set question to (display dialog my_dialog default answer "I Don't Know!" buttons {"That's my answer!", "Quit"} default button 1 cancel button 2)
set button to button returned of question
set x to text returned of question
try
if x = "" then error
set x to x as integer
on error
display dialog "Answer must be a number!" buttons {"Ok"} default button 1
my generate_question(a, b, c, type)
end try
set positive to {"you rock", "awesome", "correct", "word up", "yeah", "oh baby", "rockin", "good", "yay", "great", "fantastic", "you be so smart"}
set negative to {"lame", "idiot", "so stupid", "that was easy you are dumb", "geez", "not too bright"}
if x = answer then
say item ((random number ((count positive) - 1)) + 1) of positive
my start_program()
else
say item ((random number ((count negative)) - 1) + 1) of negative
my generate_question(a, b, c, type)
end if
end generate_question
Your way certainly works, but just so you can see something with repeat loops here’s how I would have written it. I think the script is better this way because 1) you’re not resetting the variables positive, negative, and c with every iteration of the script and 2) you’re not calculating the variable counts multiple times either. These things are done once at the beginning of the script.
I’m not sure why you generated the random numbers like ((random number (count c) - 1) + 1) instead of (random number from 1 to cCount) either. Also I usually like to set all of my variables at the beginning of the script that way I can quickly find and change things when needed.
property positive : {"you rock", "awesome", "correct", "word up", "yeah", "oh baby", "rockin", "good", "yay", "great", "fantastic", "you be so smart"}
property negative : {"lame", "idiot", "so stupid", "that was easy you are dumb", "geez", "not too bright"}
property c : {"times", "plus", "minus"}
property dialog1DefaultAnswer : "I Don't Know!"
property dialog1Buttons : {"That's my answer!", "Quit"}
property dialog2Comment : "Answer must be a number!"
property dialog2Buttons : {"Ok"}
set positiveCount to count of positive
set negativeCount to count of negative
set cCount to count of c
repeat
-- get question
set a to random number from 1 to 10
set b to random number from 10 to 99
set type to item (random number from 1 to cCount) of c
-- calculate answer
if type = "plus" then
set answer to a + b
else if type = "minus" then
set answer to a - b
else if type = "times" then
set answer to a * b
end if
-- get answer from user
set my_dialog to "Hey, What is " & (a as text) & " " & type & " " & (b as text) & "?"
repeat
display dialog my_dialog default answer dialog1DefaultAnswer buttons dialog1Buttons default button 1 cancel button 2
set {button, x} to {button returned, text returned} of result
try
if x = "" then error
set x to x as number
exit repeat
on error
display dialog dialog2Comment buttons dialog2Buttons default button 1
end try
end repeat
-- compare user answer to calculated answer
if x = answer then
say item (random number from 1 to positiveCount) of positive
else
say item (random number from 1 to negativeCount) of negative
end if
end repeat
I’ve only begun to use simple handlers in my own scripts, and have (already) found it useful on occasion to call a handler ‘from within itself’… so far without untoward incident.
Is there a specific reason you think the practice should be avoided?