Recursion
Is there any way to turn recursion errors off? So that they don't halt a handler? I've built a stack that I want to run for as long as the user dictates, on its own. I have it set for the user to choose how many minutes, hours, or times for the handler to run. This isn't just one handler, that can use send. This is a series of handlers that call on each other, with a series of if-then statements that will exit a handler or do something, before going to the next handler. The built-in exit appears to be working flawlessly. But this too much recursion stops everything when it reaches a certain point. Please tell me I can turn it off! This kills the best part of the project otherwise. Shari -- --Shareware Games for the Mac-- http://www.gypsyware.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
RE: Recursion
Is there any way to turn recursion errors off? So that they don't halt a handler? Shari -- --Shareware Games for the Mac-- http://www.gypsyware.com I don't know of any way to turn recursion errors off, however you may want to look at the recursionLimit property. This will allow you to increase the recursion limit. Remember, however, that unending recursion will eventually kill your program no matter what the limit is. This is true of any language not just Metacard. -Glen Yates -- One of your Dreamboats, remember me? :-) -- ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Re: More on recursion...
--- Shari [EMAIL PROTECTED] wrote: Also, does anyone know how Metacard keeps track of recursion? Specifically? If a handler calls another which calls another which calls the first, is this considered a handler calling itself? --- Mike replies: Shari, I'd recommend that you rewrite your code to avoid recursion completely. In the long run you will save yourself much time and effort. As for your example, let's assume that btns A,B, and C hold scripts that call each other in the manner that you describe (I'm just using btns instead of handlers). A better way is to have another btn D that controls the three btns. In btn D put the script: on mouseUp repeat 100 -- as many times as you need send mouseUp to btn A send mouseUp to btn B send mouseUp to btn C end repeat end mouseUp In your other posts you mentioned something like handlers calling each other. This should also be avoided. Recursion is one of those items like the ASCII chart that for some reason must be in all programming books. For what most of us are doing here it really is unnecessary and can cause problems. Don't take this post as being at all critical of your programming. If you want any more help just email me at [EMAIL PROTECTED] Good luck, Mike __ Do You Yahoo!? Yahoo! Finance - Get real-time stock quotes http://finance.yahoo.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Re: More on recursion...
One observation on avoiding recursion in MC - The way this 'task1' handler is written, it cannot finish executing until either 'task2' or 'task3' finishes executing, and control is returned to 'task1'; in other words, this kind of call blocks execution in the calling handler until the called handler finishes. When you have several handlers executing each other in this way, you can quickly have multiple instances of a handler in the execution path, each waiting for a subsequent (called) handler to finish running. You can make a small change in the way these handlers call each other, so that recursion never happens. Instead of this (which creates recursion): on task1 if the seconds mod 2 = 0 then task2 else task3 end if end task1 on task2 if the seconds mod 3 = 0 then task1 else task3 end if end task2 on task3 if the seconds mod 5 = 0 then task1 else task2 end if end task3 ... do it this way: on task1 if the seconds mod 2 = 0 then send task2 to me in 10 milliseconds else send task3 to me in 10 milliseconds end if end task1 on task2 if the seconds mod 3 = 0 then send task1 to me in 10 milliseconds else send task3 to me in 10 milliseconds end if end task2 on task3 if the seconds mod 5 = 0 then send task1 to me in 10 milliseconds else send task2 to me in 10 milliseconds end if end task3 By enqueuing the execution of each called handler with a brief time lag, instead of executing (calling) the called handler directly, the CALLING handler always finishes running before the CALLED one starts. That way, there's no way recursion can happen, even when a handler calls itself: on task3 if the seconds mod 5 = 0 then send task3 to me in 10 milliseconds else send task1 to me in 10 milliseconds end if end task3 I haven't tried it since about 1948 WITHOUT the time lag, but that might work too. Just the act of using send instead of a direct exec/call may break the 'execution path' so nesting and recursion don't happen. Food for thought. Phil - Original Message - From: Shari [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Thursday, August 29, 2002 7:37 AM Subject: More on recursion... Also, does anyone know how Metacard keeps track of recursion? Specifically? If a handler calls another which calls another which calls the first, is this considered a handler calling itself? -- --Shareware Games for the Mac-- http://www.gypsyware.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Re: More on recursion...
If a handler calls another which calls another which calls the first, is this considered a handler calling itself? --- Mike replies: Shari, I'd recommend that you rewrite your code to avoid recursion completely. In the long run you will save yourself much time and effort. As for your example, let's assume that btns A,B, and C hold scripts that call each other in the manner that you describe (I'm just using btns instead of handlers). A better way is to have another btn D that controls the three btns. In btn D put the script: on mouseUp repeat 100 -- as many times as you need send mouseUp to btn A send mouseUp to btn B send mouseUp to btn C end repeat end mouseUp In your other posts you mentioned something like handlers calling each other. This should also be avoided. Not doable to have all handlers called in order as described. Not all handlers run each time. So the game starts with the handler that will always start the hand (in a card game). The game analyzes a set of factors to decide what to do next. It will then call the appropriate handler. This behavior repeats itself, each handler analyzing the current state of things, and then deciding what should happen next. It will then call the appropriate handler. At some point, the hand ends, the cards are collected, and the first handler is called to start the next hand. This does not happen in the same place each time. A hand can end at different times depending on the state of things. I've set this game up specifically so that it can play all by itself. For my purposes, this is high desireable, and a very important factor in the game. So the recursion issue is an important one. I've made a few changes in the coding, such as adding in 1 millisecond to the appropriate send commands. I think this fixed it. I'm testing that now and have not encountered a recursion error yet. Question: If a handler calls itself with the send command, is this considered recursion? on playGame # do this and that send playGame to me in 1 millisecond end playGame -- --Shareware Games for the Mac-- http://www.gypsyware.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
RE: Recursion
I don't know of any way to turn recursion errors off, however you may want to look at the recursionLimit property. This will allow you to increase the recursion limit. Remember, however, that unending recursion will eventually kill your program no matter what the limit is. This is true of any language not just Metacard. -Glen Yates -- One of your Dreamboats, remember me? :-) -- Dreamboats! Yes! I do remember you ;-) I remember that Jacqueline coveted that title, and sought it for herself as well :-) In my last post, I said I thought I may have avoided the recursion errors, though I'm not yet certain. I am trying to determine exactly what Metacard thinks is recursion, and how long my program can self-run so that my users do not get an error. on theHandler # do things send theHandler to me in 1 millisecond end theHandler Would this trigger a Metacard recursion count? -- --Shareware Games for the Mac-- http://www.gypsyware.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Re: More on recursion...
That's what I'm experimenting with right now. I changed one of the most important calls by adding send to it, and then an additional (very short) time lag, just as you said. So far the tests are good. Perhaps traditional programming books talk about recursion in detail, but I've never been one for tradition. All of my programming has been done in either Hypercard or Metacard, with the corresponding documentation. And this is the first program I've created with the desire to intentionally have it keep playing with itself :-) So you were programming before I was even thought up?? (grin) One observation on avoiding recursion in MC - The way this 'task1' handler is written, it cannot finish executing until either 'task2' or 'task3' finishes executing, and control is returned to 'task1'; in other words, this kind of call blocks execution in the calling handler until the called handler finishes. When you have several handlers executing each other in this way, you can quickly have multiple instances of a handler in the execution path, each waiting for a subsequent (called) handler to finish running. You can make a small change in the way these handlers call each other, so that recursion never happens. Instead of this (which creates recursion): on task1 if the seconds mod 2 = 0 then task2 else task3 end if end task1 on task2 if the seconds mod 3 = 0 then task1 else task3 end if end task2 on task3 if the seconds mod 5 = 0 then task1 else task2 end if end task3 ... do it this way: on task1 if the seconds mod 2 = 0 then send task2 to me in 10 milliseconds else send task3 to me in 10 milliseconds end if end task1 on task2 if the seconds mod 3 = 0 then send task1 to me in 10 milliseconds else send task3 to me in 10 milliseconds end if end task2 on task3 if the seconds mod 5 = 0 then send task1 to me in 10 milliseconds else send task2 to me in 10 milliseconds end if end task3 By enqueuing the execution of each called handler with a brief time lag, instead of executing (calling) the called handler directly, the CALLING handler always finishes running before the CALLED one starts. That way, there's no way recursion can happen, even when a handler calls itself: on task3 if the seconds mod 5 = 0 then send task3 to me in 10 milliseconds else send task1 to me in 10 milliseconds end if end task3 I haven't tried it since about 1948 WITHOUT the time lag, but that might work too. Just the act of using send instead of a direct exec/call may break the 'execution path' so nesting and recursion don't happen. Food for thought. Phil - Original Message - From: Shari [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Thursday, August 29, 2002 7:37 AM Subject: More on recursion... Also, does anyone know how Metacard keeps track of recursion? Specifically? If a handler calls another which calls another which calls the first, is this considered a handler calling itself? -- --Shareware Games for the Mac-- http://www.gypsyware.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard -- --Shareware Games for the Mac-- http://www.gypsyware.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Background ops
While emailing you guys, I've got the program running in the background. Another test to see if things run smoothly. Looks good! I wasn't sure if putting Metacard in the background would allow everything to just keep right on flowing. I can see the animations and everything. Very pleased :-) I'm so close to releasing it for beta testing, I'm about to bust! Oh, that's why I got online in the first place, to place a post looking for testers you guys distracted me :-) Shari C -- --Shareware Games for the Mac-- http://www.gypsyware.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Re: Recursion
on theHandler # do things send theHandler to me in 1 millisecond end theHandler Would this trigger a Metacard recursion count? It shouldn't. What happens is this: 1. theHandler is triggered. 2. A message is queued to trigger theHandler again. 3. theHandler finishes executing. 4. theHandler is triggered by the pending message. As you can see, the first copy of the handler completes and exits in step 3. Thus, you only have one copy of the handler in memory at once. On the other hand, this: on theHandler # do things theHandler end theHandler Produces this result: 1. theHandler is triggered. 2. theHandler calls a second copy of itself. 3. The second copy calls a third. 4. The third copy calls a fourth. ... After 4 steps there are 4 handlers in memory, and you are recursing. The first copy can't release until the second does, the second is waiting for the third, the third is waiting on the fourth, etc. Until all of those handlers start terminating without recursing any further, you'll just keep on eating memory- and Metacard will bail you out with an error. HTH, Brian
Re: Recursion
Thank you, Brian. Very nice explanation. I remember you from the Yennie externals collection for Hypercard. I still have them filed away in my Hypercard helpers folder :-) Now collecting dust as I've migrated to Metacard... It's nice to use a program that doesn't need a bunch of externals! Very happy with Metacard :-) It's opened up a world of possibilities! Once the new blackjack game comes out, you can see side by side how it compares to the original Hypercard blackjack game. Just the ability to have color animations is very happy! It shouldn't. What happens is this: 1. theHandler is triggered. 2. A message is queued to trigger theHandler again. 3. theHandler finishes executing. 4. theHandler is triggered by the pending message. As you can see, the first copy of the handler completes and exits in step 3. Thus, you only have one copy of the handler in memory at once. On the other hand, this: on theHandler # do things theHandler end theHandler Produces this result: 1. theHandler is triggered. 2. theHandler calls a second copy of itself. 3. The second copy calls a third. 4. The third copy calls a fourth. ... After 4 steps there are 4 handlers in memory, and you are recursing. The first copy can't release until the second does, the second is waiting for the third, the third is waiting on the fourth, etc. Until all of those handlers start terminating without recursing any further, you'll just keep on eating memory- and Metacard will bail you out with an error. HTH, Brian -- --Shareware Games for the Mac-- http://www.gypsyware.com ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Re: More on recursion...
- Original Message - From: Shari [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Thursday, August 29, 2002 12:33 PM Subject: Re: More on recursion... That's what I'm experimenting with right now. I changed one of the most important calls by adding send to it, and then an additional (very short) time lag, just as you said. So far the tests are good. Yaay!! So you were programming before I was even thought up?? Maybe... OK, 1948 was a lie. I started in 1978 - just 8 years after the beginning of time. on calcTheBeginning put 0 into xx -- seconds since the beginning of time convert xx to date and time put xx end calcTheBeginning Phil ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Re: Recursion
Is there any way to turn recursion errors off? So that they don't halt a handler? Shari The recursion limit problem can be avoided if you don't use functions and instead use handlers that call themselves and each other by using something like send myHandler to me in 10 ticks, returning values via custom props and globals. The calling handler ends normally and the send message gets added to the pending messages. I have a project* with handlers calling themselves and others that appear to run endlessly, or at least until my patience runs out. Rich Herz [EMAIL PROTECTED] *e.g., Div 3 Lab 4, and Div 5 Labs 3 and 4 of the Reactor Lab downloadable from www.ReactorLab.net ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard
Re: More on recursion...
Michael Kann wrote/ schreef: snip Recursion is one of those items like the ASCII chart that for some reason must be in all programming books. For what most of us are doing here it really is unnecessary and can cause problems. I disagree; what is a more elegant handler to calculate 7!, faculty(7)? function faculty v if v is 1 then return 1 else return v*faculty(v-1) end faculty Or to make a list of all files (also in subfolders) in a specific folder? function deepFiles startDir set the cursor to busy if it is Cancel then exit to top set the directory to startDir local tFiles repeat for each line tFile in the files put startDir / tFile into line (the number of lines in tFiles + 1) of tFiles end repeat repeat for each line tDir in line 2 to -1 of the directories put deepFiles(startDir / tDir) into line (the number of lines in tFiles + 1) of tFiles set the directory to startDir end repeat return tFiles end deepFiles Or to repeat a string (just elegant): function repeatstring rChunk,rTimes if rTimes is 1 then return rChunk else return rChunk repeatString(rChunk,rTImes-1) end repeatstring I think, if one really thinks structured, it's possible to make things much simpler with recurred functions. snip Good luck, Mike Regards, / Groeten, Sjoerd ___ metacard mailing list [EMAIL PROTECTED] http://lists.runrev.com/mailman/listinfo/metacard