Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #12463 > unrolled thread
| Started by | Arnold Doray <invalid@invalid.com> |
|---|---|
| First post | 2012-05-26 09:39 +0000 |
| Last post | 2012-05-29 20:25 +0000 |
| Articles | 20 on this page of 65 — 11 participants |
Back to article view | Back to comp.lang.forth
More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-26 09:39 +0000
Re: More on Boolean Shortcircuiting Josh Grams <josh@qualdan.com> - 2012-05-26 12:44 +0000
Re: More on Boolean Shortcircuiting Josh Grams <josh@qualdan.com> - 2012-05-26 12:47 +0000
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-26 14:16 +0000
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-26 13:48 +0000
Re: More on Boolean Shortcircuiting Josh Grams <josh@qualdan.com> - 2012-05-27 00:17 +0000
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-26 08:27 -0700
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-26 10:25 -0700
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-27 10:47 +0000
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-27 07:00 -0700
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-27 17:20 +0000
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-27 15:03 -0700
Re: More on Boolean Shortcircuiting "David N. Williams" <williams@umich.edu> - 2012-05-26 17:17 -0400
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-26 14:49 -0700
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-27 10:21 +0000
Re: More on Boolean Shortcircuiting Josh Grams <josh@qualdan.com> - 2012-05-28 14:24 +0000
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-28 10:27 -0700
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-29 09:18 +0000
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-28 12:41 -0500
Re: More on Boolean Shortcircuiting "Elizabeth D. Rather" <erather@forth.com> - 2012-05-28 07:55 -1000
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-29 11:34 +0000
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-29 13:53 +0000
Re: More on Boolean Shortcircuiting Alex McDonald <blog@rivadpm.com> - 2012-05-29 07:02 -0700
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-30 01:45 +0000
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-29 20:02 -0700
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-30 04:27 +0000
Re: More on Boolean Shortcircuiting Alex McDonald <blog@rivadpm.com> - 2012-05-30 02:09 -0700
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-30 11:07 +0000
Re: More on Boolean Shortcircuiting Alex McDonald <blog@rivadpm.com> - 2012-05-30 04:38 -0700
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-30 06:46 -0500
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-30 13:52 +0000
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-30 09:02 -0500
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-30 14:13 +0000
Re: More on Boolean Shortcircuiting Alex McDonald <blog@rivadpm.com> - 2012-05-30 07:41 -0700
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-30 11:46 -0500
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-31 09:18 -0700
Re: More on Boolean Shortcircuiting Albert van der Horst <albert@spenarnc.xs4all.nl> - 2012-05-31 11:54 +0000
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-31 15:17 +0000
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-31 11:17 -0500
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-31 17:40 +0000
Re: More on Boolean Shortcircuiting "Elizabeth D. Rather" <erather@forth.com> - 2012-05-31 08:43 -1000
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-06-01 02:56 +0000
Re: More on Boolean Shortcircuiting anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2012-06-01 09:49 +0000
Re: More on Boolean Shortcircuiting "Elizabeth D. Rather" <erather@forth.com> - 2012-06-01 09:18 -1000
Re: More on Boolean Shortcircuiting Josh Grams <josh@qualdan.com> - 2012-05-31 16:45 +0000
Re: More on Boolean Shortcircuiting BruceMcF <agila61@netscape.net> - 2012-05-31 09:58 -0700
Re: More on Boolean Shortcircuiting Albert van der Horst <albert@spenarnc.xs4all.nl> - 2012-05-31 18:38 +0000
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-06-01 03:09 +0000
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-06-01 02:44 -0500
Re: More on Boolean Shortcircuiting Mark Wills <markrobertwills@yahoo.co.uk> - 2012-06-01 04:57 -0700
Re: More on Boolean Shortcircuiting anton@mips.complang.tuwien.ac.at (Anton Ertl) - 2012-06-01 12:45 +0000
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-06-01 08:45 -0500
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-06-01 15:18 +0000
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-30 06:39 -0500
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-29 09:52 -0500
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-30 01:48 +0000
Re: More on Boolean Shortcircuiting Gerry Jackson <gerry@jackson9000.fsnet.co.uk> - 2012-05-30 07:55 +0100
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-30 02:56 -0500
Re: More on Boolean Shortcircuiting Arnold Doray <invalid@invalid.com> - 2012-05-30 11:31 +0000
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-30 06:53 -0500
Re: More on Boolean Shortcircuiting Alex McDonald <blog@rivadpm.com> - 2012-05-30 05:04 -0700
Re: More on Boolean Shortcircuiting Andrew Haley <andrew29@littlepinkcloud.invalid> - 2012-05-30 09:03 -0500
Re: More on Boolean Shortcircuiting Gerry Jackson <gerry@jackson9000.fsnet.co.uk> - 2012-05-29 17:49 +0100
Re: More on Boolean Shortcircuiting Gerry Jackson <gerry@jackson9000.fsnet.co.uk> - 2012-05-29 19:06 +0100
Re: More on Boolean Shortcircuiting Albert van der Horst <albert@spenarnc.xs4all.nl> - 2012-05-29 20:25 +0000
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-29 11:34 +0000 |
| Message-ID | <jq2c8n$194$1@dont-email.me> |
| In reply to | #12515 |
On Mon, 28 May 2012 14:24:42 +0000, Josh Grams wrote: > I was writing some code today which reminded me of the other shortcoming > of conditional EXIT words: often you want to do some cleanup first. To > use conditional EXITs, you have to be careful to have the stack effect > the same at each exit point and clean up in a parent word. I usually > find it easier to just write the `IF ... flag EXIT THEN` out in full. > > Or you may want to put values on the rstack while you call the words > which compute the flags, and then to use conditional exits you have to > pull the stuff off the rstack and bring the flag back to the top first. > Yes. I've come across both situations, and I think the practical way to use short-circuiting is if the complex operations are packaged into a word. This makes for shorter words, but more words, as you observed before.
[toc] | [prev] | [next] | [standalone]
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-29 13:53 +0000 |
| Message-ID | <jq2kd5$f64$1@dont-email.me> |
| In reply to | #12515 |
On Mon, 28 May 2012 14:24:42 +0000, Josh Grams wrote:
> I was writing some code today which reminded me of the other shortcoming
> of conditional EXIT words: often you want to do some cleanup first. To
> use conditional EXITs, you have to be careful to have the stack effect
> the same at each exit point and clean up in a parent word. I usually
> find it easier to just write the `IF ... flag EXIT THEN` out in full.
>
> Or you may want to put values on the rstack while you call the words
> which compute the flags, and then to use conditional exits you have to
> pull the stuff off the rstack and bring the flag back to the top first.
>
> So there are some simple situations where conditional exits are useful,
> but in Forth the parameters on the stack often get in the way. This
> doesn't happen in languages with named parameters.
>
Here's an example involving cleanup:
You have an image, and the task is to retrieve the image's timestamp
using OCR. To do this, there are two words available.
: img2int ( img n1 n2 n3 n4 -- n f ) ... ;
: ymdhm ( y m d h m -- time ) ... ;
The word IMG2INT takes 4 coordinates on the image, which enclose an
integer, crops the image to those coordinates, runs the OCR program and
parses the resulting string into an integer. The return value is the
integer and a flag indicating success/failure.
YMDHM takes 5 integers (year, month, day, hour, minute) and converts this
to an internal time format. A time of 0 could indicate an OCR failure.
The images come from different sources, so the coordinates n1..n4 would
vary by image source.
Here's a solution using the shortcircuit operators:
: | ` if ` true ` exit ` then ; immediate
: -> ` not ` if ` exit ` then ; immediate
: year ( img n1 n2 n3 n4 -- m f )
img2int | drop 0 false ;
: month ( img n1 n2 n3 n4 -- m f )
img2int | drop drop 0 false ;
: day ( img n1 n2 n3 n4 -- m f )
img2int | drop drop drop 0 false ;
: hour ( img n1 n2 n3 n4 -- m f )
img2int | drop drop drop drop 0 false ;
: minute ( img n1 n2 n3 n4 -- m f )
img2int | drop drop drop drop drop 0 false ;
\ Gets timestamps from image source XYZ
: timestamp-xyz { img } ( img -- time )
img 91 13 158 35 year ->
img 158 13 194 35 month ->
img 194 13 233 35 day ->
img 233 13 268 35 hour ->
img 277 13 310 35 minute ->
ymdhm ;
\ Gets timestamps from image source JKL
: timestamp-jkl { img } ( img -- time )
img 170 13 245 40 year ->
img 245 13 289 40 month ->
img 289 13 331 40 day ->
img 331 13 372 40 hour ->
img 381 13 420 40 minute ->
ymdhm ;
As you can see the cleanup is done in the words like YEAR, MONTH etc, and
factoring it this way looks natural IMHO.
Yet, as others have noted, passing the flag is an inefficiency, since we
re-test the same flag downstream.
Cheers,
Arnold
[toc] | [prev] | [next] | [standalone]
| From | Alex McDonald <blog@rivadpm.com> |
|---|---|
| Date | 2012-05-29 07:02 -0700 |
| Message-ID | <232dc052-32f3-458d-b0cd-bcf7365827ac@cu1g2000vbb.googlegroups.com> |
| In reply to | #12548 |
On May 29, 2:53 pm, Arnold Doray <inva...@invalid.com> wrote:
> On Mon, 28 May 2012 14:24:42 +0000, Josh Grams wrote:
> > I was writing some code today which reminded me of the other shortcoming
> > of conditional EXIT words: often you want to do some cleanup first. To
> > use conditional EXITs, you have to be careful to have the stack effect
> > the same at each exit point and clean up in a parent word. I usually
> > find it easier to just write the `IF ... flag EXIT THEN` out in full.
>
> > Or you may want to put values on the rstack while you call the words
> > which compute the flags, and then to use conditional exits you have to
> > pull the stuff off the rstack and bring the flag back to the top first.
>
> > So there are some simple situations where conditional exits are useful,
> > but in Forth the parameters on the stack often get in the way. This
> > doesn't happen in languages with named parameters.
>
> Here's an example involving cleanup:
>
> You have an image, and the task is to retrieve the image's timestamp
> using OCR. To do this, there are two words available.
>
> : img2int ( img n1 n2 n3 n4 -- n f ) ... ;
> : ymdhm ( y m d h m -- time ) ... ;
>
> The word IMG2INT takes 4 coordinates on the image, which enclose an
> integer, crops the image to those coordinates, runs the OCR program and
> parses the resulting string into an integer. The return value is the
> integer and a flag indicating success/failure.
>
> YMDHM takes 5 integers (year, month, day, hour, minute) and converts this
> to an internal time format. A time of 0 could indicate an OCR failure.
>
> The images come from different sources, so the coordinates n1..n4 would
> vary by image source.
>
> Here's a solution using the shortcircuit operators:
>
> : | ` if ` true ` exit ` then ; immediate
> : -> ` not ` if ` exit ` then ; immediate
>
> : year ( img n1 n2 n3 n4 -- m f )
> img2int | drop 0 false ;
>
> : month ( img n1 n2 n3 n4 -- m f )
> img2int | drop drop 0 false ;
>
> : day ( img n1 n2 n3 n4 -- m f )
> img2int | drop drop drop 0 false ;
>
> : hour ( img n1 n2 n3 n4 -- m f )
> img2int | drop drop drop drop 0 false ;
>
> : minute ( img n1 n2 n3 n4 -- m f )
> img2int | drop drop drop drop drop 0 false ;
>
> \ Gets timestamps from image source XYZ
> : timestamp-xyz { img } ( img -- time )
> img 91 13 158 35 year ->
> img 158 13 194 35 month ->
> img 194 13 233 35 day ->
> img 233 13 268 35 hour ->
> img 277 13 310 35 minute ->
> ymdhm ;
>
> \ Gets timestamps from image source JKL
> : timestamp-jkl { img } ( img -- time )
> img 170 13 245 40 year ->
> img 245 13 289 40 month ->
> img 289 13 331 40 day ->
> img 331 13 372 40 hour ->
> img 381 13 420 40 minute ->
> ymdhm ;
>
> As you can see the cleanup is done in the words like YEAR, MONTH etc, and
> factoring it this way looks natural IMHO.
>
> Yet, as others have noted, passing the flag is an inefficiency, since we
> re-test the same flag downstream.
>
> Cheers,
> Arnold
Would CATCH/THROW not be easier? (And shorter?)
[toc] | [prev] | [next] | [standalone]
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-30 01:45 +0000 |
| Message-ID | <jq3u4a$svm$1@dont-email.me> |
| In reply to | #12549 |
On Tue, 29 May 2012 07:02:09 -0700, Alex McDonald wrote: > > Would CATCH/THROW not be easier? (And shorter?) Probably my misunderstanding of how exceptions work in forth. In the forth I wrote, THROW simply sets an exception flag, which forces all words downstream to return immediately until it meets CATCH. THROW doesn't clear the stack. In any case, there are other items on the stack that should not be cleared. Could you elaborate on the solution you're thinking of? Cheers, Arnold
[toc] | [prev] | [next] | [standalone]
| From | BruceMcF <agila61@netscape.net> |
|---|---|
| Date | 2012-05-29 20:02 -0700 |
| Message-ID | <dadc1d97-9e12-4712-a432-6c7922e08754@b1g2000vbb.googlegroups.com> |
| In reply to | #12578 |
On May 29, 9:45 pm, Arnold Doray <inva...@invalid.com> wrote: > On Tue, 29 May 2012 07:02:09 -0700, Alex McDonald wrote: > > > Would CATCH/THROW not be easier? (And shorter?) > Probably my misunderstanding of how exceptions work in forth. In the > forth I wrote, THROW simply sets an exception flag, which forces all > words downstream to return immediately until it meets CATCH. THROW > doesn't clear the stack. It should. To THROW an exception the return and data stack should return to the depth when CATCH executed the xt, plus the non-zero throw code. The stack frame often includes the data stack depth when CATCH executed and the return stack depth of the previous CATCH, and the return stack depth of the stack frame stored in a variable, plus whatever info you need to restore input state.
[toc] | [prev] | [next] | [standalone]
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-30 04:27 +0000 |
| Message-ID | <jq47j5$bb4$1@dont-email.me> |
| In reply to | #12580 |
On Tue, 29 May 2012 20:02:21 -0700, BruceMcF wrote: > On May 29, 9:45 pm, Arnold Doray <inva...@invalid.com> wrote: >> On Tue, 29 May 2012 07:02:09 -0700, Alex McDonald wrote: >> >> > Would CATCH/THROW not be easier? (And shorter?) > >> Probably my misunderstanding of how exceptions work in forth. In the >> forth I wrote, THROW simply sets an exception flag, which forces all >> words downstream to return immediately until it meets CATCH. THROW >> doesn't clear the stack. > > It should. To THROW an exception the return and data stack should return > to the depth when CATCH executed the xt, plus the non-zero throw code. > The stack frame often includes the data stack depth when CATCH executed > and the return stack depth of the previous CATCH, and the return stack > depth of the stack frame stored in a variable, plus whatever info you > need to restore input state. What happens if the word activated by CATCH consumes the stack below the level of that on the depth during the time CATCH executed? Does CATCH save a snapshot of the data & return stack? This isn't what Gforth does: : a drop 777 throw ; ok : b ['] a catch ; ok 1 2 3 b ok .S <4> 1 2 4428054488 777 ok I'm probably missing something , but this kind of exception propagation seems more trouble than it is worth.... Cheers, Arnold
[toc] | [prev] | [next] | [standalone]
| From | Alex McDonald <blog@rivadpm.com> |
|---|---|
| Date | 2012-05-30 02:09 -0700 |
| Message-ID | <eeb8e07a-9c00-4e87-a41c-37ab3a25f551@8g2000vbu.googlegroups.com> |
| In reply to | #12581 |
On May 30, 5:27 am, Arnold Doray <inva...@invalid.com> wrote: > On Tue, 29 May 2012 20:02:21 -0700, BruceMcF wrote: > > On May 29, 9:45 pm, Arnold Doray <inva...@invalid.com> wrote: > >> On Tue, 29 May 2012 07:02:09 -0700, Alex McDonald wrote: > > >> > Would CATCH/THROW not be easier? (And shorter?) > > >> Probably my misunderstanding of how exceptions work in forth. In the > >> forth I wrote, THROW simply sets an exception flag, which forces all > >> words downstream to return immediately until it meets CATCH. THROW > >> doesn't clear the stack. > > > It should. To THROW an exception the return and data stack should return > > to the depth when CATCH executed the xt, plus the non-zero throw code. > > The stack frame often includes the data stack depth when CATCH executed > > and the return stack depth of the previous CATCH, and the return stack > > depth of the stack frame stored in a variable, plus whatever info you > > need to restore input state. > > What happens if the word activated by CATCH consumes the stack below the > level of that on the depth during the time CATCH executed? Does CATCH > save a snapshot of the data & return stack? This isn't what Gforth does: > > : a drop 777 throw ; ok > : b ['] a catch ; ok > 1 2 3 b ok > .S <4> 1 2 4428054488 777 ok > > I'm probably missing something , but this kind of exception propagation > seems more trouble than it is worth.... > > Cheers, > Arnold Try it with a stack diagram. : dropit ( n -- ) drop 777 throw ; : testit ( a b c d -- ) ['] dropit catch if ( a b c ? ) else ( a b c ) then ... ; The question mark indicates values you can't trust; the depth is as before the execution, and the untrustworthy values as those for the stack diagram on the word CATCHed.
[toc] | [prev] | [next] | [standalone]
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-30 11:07 +0000 |
| Message-ID | <jq4v1e$p2s$1@dont-email.me> |
| In reply to | #12585 |
On Wed, 30 May 2012 02:09:52 -0700, Alex McDonald wrote: > On May 30, 5:27 am, Arnold Doray <inva...@invalid.com> wrote: >> On Tue, 29 May 2012 20:02:21 -0700, BruceMcF wrote: >> > On May 29, 9:45 pm, Arnold Doray <inva...@invalid.com> wrote: >> >> On Tue, 29 May 2012 07:02:09 -0700, Alex McDonald wrote: >> >> >> > Would CATCH/THROW not be easier? (And shorter?) >> >> >> Probably my misunderstanding of how exceptions work in forth. In the >> >> forth I wrote, THROW simply sets an exception flag, which forces all >> >> words downstream to return immediately until it meets CATCH. THROW >> >> doesn't clear the stack. >> >> > It should. To THROW an exception the return and data stack should >> > return to the depth when CATCH executed the xt, plus the non-zero >> > throw code. The stack frame often includes the data stack depth when >> > CATCH executed and the return stack depth of the previous CATCH, and >> > the return stack depth of the stack frame stored in a variable, plus >> > whatever info you need to restore input state. >> >> What happens if the word activated by CATCH consumes the stack below >> the level of that on the depth during the time CATCH executed? Does >> CATCH save a snapshot of the data & return stack? This isn't what >> Gforth does: >> >> : a drop 777 throw ; ok : b ['] a catch ; ok 1 2 3 b ok .S <4> 1 2 >> 4428054488 777 ok >> >> I'm probably missing something , but this kind of exception propagation >> seems more trouble than it is worth.... >> >> Cheers, >> Arnold > > Try it with a stack diagram. > > : dropit ( n -- ) drop 777 throw ; > : testit ( a b c d -- ) ['] dropit catch if ( a b c ? ) else ( a b c ) > then ... ; > > The question mark indicates values you can't trust; the depth is as > before the execution, and the untrustworthy values as those for the > stack diagram on the word CATCHed. Understood. But it looks pretty brittle to me, especially if multiple exceptions could be thrown or at a much higher upstream the calling hierarchy. For example, if there were say five THROWS upstream you'd be hard pressed trying to clean up the mess at CATCH, even with your stack diagrams. Ditto for an exception thrown in another module in some private word. And to top it all, you're left to clean up a mess far from where it was created. Simply horrible. I'm guessing this scheme works best when the stack is not consumed, but added to upstream. My instinct was to not bother cleaning up the stack because of these ambiguities. It's blatantly non-standard of course, but I am more concerned about utility. IMHO the mess should be cleaned up at THROW, not at CATCH. However, I am certain the standard is well thought out, and I am missing something. Cheers, Arnold
[toc] | [prev] | [next] | [standalone]
| From | Alex McDonald <blog@rivadpm.com> |
|---|---|
| Date | 2012-05-30 04:38 -0700 |
| Message-ID | <5ec74979-9f16-4b50-a228-93274c9bdea9@3g2000vbx.googlegroups.com> |
| In reply to | #12591 |
On May 30, 12:07 pm, Arnold Doray <inva...@invalid.com> wrote: > On Wed, 30 May 2012 02:09:52 -0700, Alex McDonald wrote: > > On May 30, 5:27 am, Arnold Doray <inva...@invalid.com> wrote: > >> On Tue, 29 May 2012 20:02:21 -0700, BruceMcF wrote: > >> > On May 29, 9:45 pm, Arnold Doray <inva...@invalid.com> wrote: > >> >> On Tue, 29 May 2012 07:02:09 -0700, Alex McDonald wrote: > > >> >> > Would CATCH/THROW not be easier? (And shorter?) > > >> >> Probably my misunderstanding of how exceptions work in forth. In the > >> >> forth I wrote, THROW simply sets an exception flag, which forces all > >> >> words downstream to return immediately until it meets CATCH. THROW > >> >> doesn't clear the stack. > > >> > It should. To THROW an exception the return and data stack should > >> > return to the depth when CATCH executed the xt, plus the non-zero > >> > throw code. The stack frame often includes the data stack depth when > >> > CATCH executed and the return stack depth of the previous CATCH, and > >> > the return stack depth of the stack frame stored in a variable, plus > >> > whatever info you need to restore input state. > > >> What happens if the word activated by CATCH consumes the stack below > >> the level of that on the depth during the time CATCH executed? Does > >> CATCH save a snapshot of the data & return stack? This isn't what > >> Gforth does: > > >> : a drop 777 throw ; ok : b ['] a catch ; ok 1 2 3 b ok .S <4> 1 2 > >> 4428054488 777 ok > > >> I'm probably missing something , but this kind of exception propagation > >> seems more trouble than it is worth.... > > >> Cheers, > >> Arnold > > > Try it with a stack diagram. > > > : dropit ( n -- ) drop 777 throw ; > > : testit ( a b c d -- ) ['] dropit catch if ( a b c ? ) else ( a b c ) > > then ... ; > > > The question mark indicates values you can't trust; the depth is as > > before the execution, and the untrustworthy values as those for the > > stack diagram on the word CATCHed. > > Understood. But it looks pretty brittle to me, especially if multiple > exceptions could be thrown or at a much higher upstream the calling > hierarchy. For example, if there were say five THROWS upstream you'd be > hard pressed trying to clean up the mess at CATCH, even with your stack > diagrams. Ditto for an exception thrown in another module in some private > word. And to top it all, you're left to clean up a mess far from where it > was created. Simply horrible. I'm guessing this scheme works best when > the stack is not consumed, but added to upstream. Why so? If the stack diagram of the word I'm catching is TRUBBLE ( a b -- c ) then ( x a b ) ' TRUBBLE CATCH will produce either ( x a b -- x ? ? nonzero ) or ( x a b -- x c zero ) regardless of where the THROW occurs. If that's not the case and you get back ( x a b -- ? ? ? nonzero ), then your stack diagram ( a b -- c ) is wrong, and the word doesn't act on the stack as the stack diagram claims it does. That's regardless of what the word does in terms of calling other words that might do their own THROWs; in this case, it should have been ( a b c -- d e ). > > My instinct was to not bother cleaning up the stack because of these > ambiguities. It's blatantly non-standard of course, but I am more > concerned about utility. IMHO the mess should be cleaned up at THROW, not > at CATCH. There's no mess to clean up, apart from a known-in-advance-number of corrupted stack entries that need dropped or replaced. Cleaning up on THROW can be -- as your short circuits are demonstrating -- horribly messy. > > However, I am certain the standard is well thought out, and I am missing > something. > > Cheers, > Arnold
[toc] | [prev] | [next] | [standalone]
| From | Andrew Haley <andrew29@littlepinkcloud.invalid> |
|---|---|
| Date | 2012-05-30 06:46 -0500 |
| Message-ID | <wZKdnQwKfNEJlVvSnZ2dnUVZ_rCdnZ2d@supernews.com> |
| In reply to | #12591 |
Arnold Doray <invalid@invalid.com> wrote:
> Understood. But it looks pretty brittle to me, especially if
> multiple exceptions could be thrown or at a much higher upstream the
> calling hierarchy. For example, if there were say five THROWS
> upstream you'd be hard pressed trying to clean up the mess at CATCH,
> even with your stack diagrams.
This doesn't make sense. The stack is restored to whatever depth is
was at CATCH.
> Ditto for an exception thrown in another module in some private
> word.
Exceptions are part of a word's API: any caller must know what they
throw. You have to catch the exceptions.
> And to top it all, you're left to clean up a mess far from
> where it was created. Simply horrible. I'm guessing this scheme
> works best when the stack is not consumed, but added to upstream.
There really is no problem.
Look how much easier it is:
xx constant scan-error
// img2int reuturns either 0 (it's OK) or a scanning error code.
: img2int ( img n1 n2 n3 n4 -- n t ) ... ;
: ymdhm ( y m d h m -- time ) ... ;
: ocr ( img n1 n2 n3 n4 -- m f )
img2int throw ;
\ Gets timestamps from image source XYZ
: (timestamp-xyz) { img } ( img -- time )
img 91 13 158 35 ocr
img 158 13 194 35 ocr
img 194 13 233 35 ocr
img 233 13 268 35 ocr
img 277 13 310 35 ocr
ymdhm ;
: timestamp-xyz { img } ( img -- time )
['] (timestamp-xyz) catch
dup scanning-error = if drop 0 else throw then ;
Andrew.
[toc] | [prev] | [next] | [standalone]
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-30 13:52 +0000 |
| Message-ID | <jq58ml$25h$1@dont-email.me> |
| In reply to | #12596 |
On Wed, 30 May 2012 06:46:28 -0500, Andrew Haley wrote: >> Understood. But it looks pretty brittle to me, especially if multiple >> exceptions could be thrown or at a much higher upstream the calling >> hierarchy. For example, if there were say five THROWS upstream you'd be >> hard pressed trying to clean up the mess at CATCH, >> even with your stack diagrams. > > This doesn't make sense. The stack is restored to whatever depth is was > at CATCH. > >> Ditto for an exception thrown in another module in some private word. > > Exceptions are part of a word's API: any caller must know what they > throw. You have to catch the exceptions. What I am having trouble understanding is the necessity to put junk on the stack once it is consumed below the levels prior to CATCH being issued. This junk invariably has to be cleared for the program to proceed, so why bother putting it in the first place? Alex McDonald has given a simple mechanism for junk-clearing by looking at the stack comments, but it doesn't work well for a THROW issued right up the hierarchy ( too much to track ) or if there are multiple THROWS that could be thrown ( multiple failure modes ). And if there really is a need to put in junk, why not consistently put in 0s? That at least makes for consistent behaviour, simplifying debugging. But all this is besides the point. Why have junk at all? What's so special about stack depth that it needs to be preserved??? Stack clearing on THROW is certainly very useful in one narrow context -- when the stack before pre-CATCH is never disturbed, but that seems unrealistic in the vast majority of scenarious where THROW...CATCH is useful. What might be useful is saving a copy of the data & return stacks and restoring them on error. But that's a lot of overhead of course and entirely unpracticable in constrained environments. Which is why my intuition says that the sensible thing is to do nothing, and accept that cleanup has to be done manually. Cheers, Arnold
[toc] | [prev] | [next] | [standalone]
| From | Andrew Haley <andrew29@littlepinkcloud.invalid> |
|---|---|
| Date | 2012-05-30 09:02 -0500 |
| Message-ID | <rOadnWCXe7jytVvSnZ2dnUVZ_rednZ2d@supernews.com> |
| In reply to | #12599 |
Arnold Doray <invalid@invalid.com> wrote: > On Wed, 30 May 2012 06:46:28 -0500, Andrew Haley wrote: > >>> Understood. But it looks pretty brittle to me, especially if multiple >>> exceptions could be thrown or at a much higher upstream the calling >>> hierarchy. For example, if there were say five THROWS upstream you'd be >>> hard pressed trying to clean up the mess at CATCH, >>> even with your stack diagrams. >> >> This doesn't make sense. The stack is restored to whatever depth is was >> at CATCH. >> >>> Ditto for an exception thrown in another module in some private word. >> >> Exceptions are part of a word's API: any caller must know what they >> throw. You have to catch the exceptions. > > What I am having trouble understanding is the necessity to put junk on > the stack once it is consumed below the levels prior to CATCH being > issued. This junk invariably has to be cleared for the program to > proceed, so why bother putting it in the first place? Because at the point of the CATCH, you know how many items you put on the stack. You don't know how many items were on the stack at the point of the THROW. It would be unusuable any other way. > Alex McDonald has given a simple mechanism for junk-clearing by looking > at the stack comments, but it doesn't work well for a THROW issued right > up the hierarchy ( too much to track ) or if there are multiple THROWS > that could be thrown ( multiple failure modes ). And if there really is a > need to put in junk, why not consistently put in 0s? Because it's a waste of time. > That at least makes for consistent behaviour, simplifying > debugging. But all this is besides the point. Why have junk at all? > What's so special about stack depth that it needs to be preserved??? Otherwise you'd get a stack underflow or overflow. > Stack clearing on THROW is certainly very useful in one narrow > context -- when the stack before pre-CATCH is never disturbed, but > that seems unrealistic in the vast majority of scenarious where > THROW...CATCH is useful. No, the whole idea of resetting the stack on a throw is that you don't need to know what nappens between a CATCH and a THROW . > What might be useful is saving a copy of the data & return stacks and > restoring them on error. But that's a lot of overhead of course and > entirely unpracticable in constrained environments. Which is why my > intuition says that the sensible thing is to do nothing, and accept that > cleanup has to be done manually. Why? You only have to remove what you put there, and let the system do the rest. Andrew.
[toc] | [prev] | [next] | [standalone]
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-30 14:13 +0000 |
| Message-ID | <jq59tt$25h$3@dont-email.me> |
| In reply to | #12600 |
On Wed, 30 May 2012 09:02:23 -0500, Andrew Haley wrote: > No, the whole idea of resetting the stack on a throw is that you don't > need to know what nappens between a CATCH and a THROW . That's just the point -- you DO need to know. You have to know to react to potential junk on your stack after CATCH.
[toc] | [prev] | [next] | [standalone]
| From | Alex McDonald <blog@rivadpm.com> |
|---|---|
| Date | 2012-05-30 07:41 -0700 |
| Message-ID | <359ef77b-11b9-4986-9902-e84f5afef0c7@nj8g2000pbc.googlegroups.com> |
| In reply to | #12603 |
On May 30, 3:13 pm, Arnold Doray <inva...@invalid.com> wrote: > On Wed, 30 May 2012 09:02:23 -0500, Andrew Haley wrote: > > No, the whole idea of resetting the stack on a throw is that you don't > > need to know what nappens between a CATCH and a THROW . > > That's just the point -- you DO need to know. You have to know to react > to potential junk on your stack after CATCH. You don't need to know any more than the stack sig. If it's ( a b c -- whatever ) then on a non-zero return from CATCH, a b and c are potentially junk. The reaction to junk should be to just drop it. Why are they there? Why not have it done automatically? Because the compiler doesn't know the stack effects of what is being executed by CATCH; all it knows is the stack depth at that point in the execution, which it faithfully restores on a THROW. On the other hand, the programmer knows (or should know if it's to work as advertised) the stack effects of the called word, but doesn't know the stack depth at the point of execution of the word. If you need what you sent to the offending word, DUP it. : SENDIT ( addr len -- ) ...long involved stuff that might fail... if THROW then ; : TRYSENDINGIT ( addr len -- ) 2dup ['] sendit catch if 2drop type ." couldn't be sent" else type ." was delivered" then ;
[toc] | [prev] | [next] | [standalone]
| From | Andrew Haley <andrew29@littlepinkcloud.invalid> |
|---|---|
| Date | 2012-05-30 11:46 -0500 |
| Message-ID | <aOCdnVdpifJs01vSnZ2dnUVZ_oqdnZ2d@supernews.com> |
| In reply to | #12603 |
Arnold Doray <invalid@invalid.com> wrote: > On Wed, 30 May 2012 09:02:23 -0500, Andrew Haley wrote: > >> No, the whole idea of resetting the stack on a throw is that you don't >> need to know what nappens between a CATCH and a THROW . > > That's just the point -- you DO need to know. You have to know to react > to potential junk on your stack after CATCH. No, you don't. You just DROP whatever you put there before you called CATCH . Andrew.
[toc] | [prev] | [next] | [standalone]
| From | BruceMcF <agila61@netscape.net> |
|---|---|
| Date | 2012-05-31 09:18 -0700 |
| Message-ID | <b8e71823-a927-4c09-a6bd-2afde7503188@pr7g2000pbb.googlegroups.com> |
| In reply to | #12603 |
On May 30, 10:13 am, Arnold Doray <inva...@invalid.com> wrote: > On Wed, 30 May 2012 09:02:23 -0500, Andrew Haley wrote: > > No, the whole idea of resetting the stack on a throw is that you don't > > need to know what nappens between a CATCH and a THROW . > That's just the point -- you DO need to know. You have to know to react > to potential junk on your stack after CATCH. And since you have checked the throw code, you know what potential junk there may be. If the xt takes ( ca1 ca2 u ) and the exception you are looking at has consumed ca1 and u and ca2 is still there, you know that on the exception return, the stack is ( ca1 x1 x2 throw# )
[toc] | [prev] | [next] | [standalone]
| From | Albert van der Horst <albert@spenarnc.xs4all.nl> |
|---|---|
| Date | 2012-05-31 11:54 +0000 |
| Message-ID | <m4vyf5.eg3@spenarnc.xs4all.nl> |
| In reply to | #12599 |
In article <jq58ml$25h$1@dont-email.me>, Arnold Doray <invalid@invalid.com> wrote: <SNIP> > >Stack clearing on THROW is certainly very useful in one narrow context -- >when the stack before pre-CATCH is never disturbed, but that seems >unrealistic in the vast majority of scenarious where THROW...CATCH is >useful. Have you experience using Forth's CATCH THROW? Probably not, because the above is patently untrue. I have experience and this is what I would say: " One would be hard pressed to come up with a realistic example where the stack after a CATCH is disturbed beyond the data passed to the word that is executed. " What do you have in mind? Do you think CATCH is used to recover from program errors where you accidentally underflow the data stack? <SNIP> > >Cheers, >Arnold > > > > > > > > > > > -- -- Albert van der Horst, UTRECHT,THE NETHERLANDS Economic growth -- being exponential -- ultimately falters. albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
[toc] | [prev] | [next] | [standalone]
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-31 15:17 +0000 |
| Message-ID | <jq822d$4a8$1@dont-email.me> |
| In reply to | #12632 |
On Thu, 31 May 2012 11:54:41 +0000, Albert van der Horst wrote: > > Have you experience using Forth's CATCH THROW? Probably not, because the > above is patently untrue. > > I have experience and this is what I would say: > > " > One would be hard pressed to come up with a realistic example where the > stack after a CATCH is disturbed beyond the data passed to the word that > is executed. > " > > What do you have in mind? > Do you think CATCH is used to recover from program errors where you > accidentally underflow the data stack? > I have just come from the Java world, where deep exceptions (those thrown well up in the calling hierarchy) are the norm. Java deals with this by allowing the programmer to trace the exception's propagation through the call hierarchy, so you can see immediately what went wrong. Deep exceptions are a byproduct of modular programming / programming with libraries. The "problem" I see with THROW's behaviour is that just *before* an exception is thrown, the stack could have been: A) Added to -- in which case THROW does a useful thing by dropping all the stuff generated by the XT that CATCH executed. B) Depleted -- in which you get junk on the stack. You have to manually clean these or drop the entire stack. C) Muddled (ie, items added to / removed ) -- in which case you are likely to just drop the entire stack. I guess in B and C, you would just drop the entire stack? IMHO, B and C are likely to occur in larger bodies of code. And A would only happen when you knew exactly where those exceptions would be thrown (ie, code you wrote yourself, not locked away in a library). Is this the right way of seeing it? Cheers, Arnold
[toc] | [prev] | [next] | [standalone]
| From | Andrew Haley <andrew29@littlepinkcloud.invalid> |
|---|---|
| Date | 2012-05-31 11:17 -0500 |
| Message-ID | <ObCdncNwwe0RBFrSnZ2dnUVZ_rKdnZ2d@supernews.com> |
| In reply to | #12636 |
Arnold Doray <invalid@invalid.com> wrote:
> On Thu, 31 May 2012 11:54:41 +0000, Albert van der Horst wrote:
>
>>
>> Have you experience using Forth's CATCH THROW? Probably not, because the
>> above is patently untrue.
>>
>> I have experience and this is what I would say:
>>
>> "
>> One would be hard pressed to come up with a realistic example where the
>> stack after a CATCH is disturbed beyond the data passed to the word that
>> is executed.
>> "
>>
>> What do you have in mind?
>> Do you think CATCH is used to recover from program errors where you
>> accidentally underflow the data stack?
>
> I have just come from the Java world, where deep exceptions (those thrown
> well up in the calling hierarchy) are the norm. Java deals with this by
> allowing the programmer to trace the exception's propagation through the
> call hierarchy, so you can see immediately what went wrong. Deep
> exceptions are a byproduct of modular programming / programming with
> libraries.
>
> The "problem" I see with THROW's behaviour is that just *before* an
> exception is thrown, the stack could have been:
>
> A) Added to -- in which case THROW does a useful thing by dropping all
> the stuff generated by the XT that CATCH executed.
>
> B) Depleted -- in which you get junk on the stack. You have to manually
> clean these or drop the entire stack.
>
> C) Muddled (ie, items added to / removed ) -- in which case you are
> likely to just drop the entire stack.
No, that's wrong. I think an example is needed.
Let's say you have a word FOO that takes three cells and returns one.
Like this:
: foo ( n1 n2 n3 - n) ... ;
However, FOO occasionally throws an exception, so you want to call it
via a CATCH. If the word FOO succeeds, you print its result,
otherwise you print "err".
The code is:
: foo ( n1 n2 n3 - n)
rot
random 10 mod 0= throw
rot rot
random 10 mod 0= throw
+ *
random 10 mod 0= throw ;
: sum
['] foo catch if drop drop drop ." err" else . then ;
This code is right regardless of whether the stack is depeted, added
to, or muddled. It does not protect you from FOO taking things off
the stack that it shouldn't. FOO can throw an exception if the stack
is muddled, or when it's depleted.
So, we put a couple of numbers on the stack.
66 77 ok
9 3 4 sum err ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum err ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum err ok
9 3 4 sum err ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum err ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum err ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
9 3 4 sum 63 ok
.s
66 77 <-Top ok
Andrew.
[toc] | [prev] | [next] | [standalone]
| From | Arnold Doray <invalid@invalid.com> |
|---|---|
| Date | 2012-05-31 17:40 +0000 |
| Message-ID | <jq8aem$o12$1@dont-email.me> |
| In reply to | #12637 |
On Thu, 31 May 2012 11:17:16 -0500, Andrew Haley wrote:
>>
>> B) Depleted -- in which you get junk on the stack. You have to manually
>> clean these or drop the entire stack.
>>
>> C) Muddled (ie, items added to / removed ) -- in which case you are
>> likely to just drop the entire stack.
>
> No, that's wrong. I think an example is needed.
>
<snip>
Crystal clear. Excellent example.
In a nutshell, CATCH's XT *consumes* its l.h.s. stack sig, so that on an
error return, those items must conservatively be considered junk because
of THROW's behaviour. And as long as all callers upstream stick to their
lhs stack sigs, this condition is never violated. It is impossible to get
junk farther down the stack. So you only need to DROP those items. That's
precisely why THROW needs to resize the stacks to their pre CATCH
conditions -- to make this guarantee. It's also why filling it with junk
is ok -- because you know exactly how much to drop, and that can't be
decided by the compiler beforehand. That's pretty smart and a very good
reason.
But of course, it doesn't protect you from bugs, as you say.
I realize now that a number of you (you, Alex, Bruce etc) were saying
exactly the same thing upthread, but the penny didn't drop until just
now. What also helped was that I just changed my THROW/CATCH to standard
Forth's behaviour and found that:
>
> : grab-timestamp-jkl { img } ( img -- y m d h m | error )
> img 170 13 245 40 &
> img 245 13 289 40 &
> img 289 13 331 40 &
> img 331 13 372 40 &
> img 381 13 420 40 & ;
>
> : timestamp-jkl ( img -- time )
> ['] grab-timestamp-jkl catch if 0 else ymdhm then ;
Should be:
: timestamp-jkl ( img -- time )
['] grab-timestamp-jkl catch if DROP 0 else ymdhm then ;
because img is consumed by GRAB-TIMESTAMP-JKL.
Thank you again for all your help. It is much appreciated.
Cheers,
Arnold
[toc] | [prev] | [next] | [standalone]
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
Back to top | Article view | comp.lang.forth
csiph-web