Recursion

2002-08-29 Thread Shari

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

2002-08-29 Thread Yates, Glen

 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...

2002-08-29 Thread Michael Kann

--- 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...

2002-08-29 Thread Phil Davis

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...

2002-08-29 Thread Shari

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

2002-08-29 Thread Shari

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...

2002-08-29 Thread Shari

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

2002-08-29 Thread Shari

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

2002-08-29 Thread Yennie

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

2002-08-29 Thread Shari

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...

2002-08-29 Thread Phil Davis

- 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

2002-08-29 Thread Richard K. Herz

 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...

2002-08-29 Thread Sjoerd Op 't Land

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