Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #12463 > unrolled thread

More on Boolean Shortcircuiting

Started byArnold Doray <invalid@invalid.com>
First post2012-05-26 09:39 +0000
Last post2012-05-29 20:25 +0000
Articles 20 on this page of 65 — 11 participants

Back to article view | Back to comp.lang.forth


Contents

  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 →


#12543

FromArnold Doray <invalid@invalid.com>
Date2012-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]


#12548

FromArnold Doray <invalid@invalid.com>
Date2012-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]


#12549

FromAlex McDonald <blog@rivadpm.com>
Date2012-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]


#12578

FromArnold Doray <invalid@invalid.com>
Date2012-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]


#12580

FromBruceMcF <agila61@netscape.net>
Date2012-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]


#12581

FromArnold Doray <invalid@invalid.com>
Date2012-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]


#12585

FromAlex McDonald <blog@rivadpm.com>
Date2012-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]


#12591

FromArnold Doray <invalid@invalid.com>
Date2012-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]


#12595

FromAlex McDonald <blog@rivadpm.com>
Date2012-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]


#12596

FromAndrew Haley <andrew29@littlepinkcloud.invalid>
Date2012-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]


#12599

FromArnold Doray <invalid@invalid.com>
Date2012-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]


#12600

FromAndrew Haley <andrew29@littlepinkcloud.invalid>
Date2012-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]


#12603

FromArnold Doray <invalid@invalid.com>
Date2012-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]


#12606

FromAlex McDonald <blog@rivadpm.com>
Date2012-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]


#12612

FromAndrew Haley <andrew29@littlepinkcloud.invalid>
Date2012-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]


#12639

FromBruceMcF <agila61@netscape.net>
Date2012-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]


#12632

FromAlbert van der Horst <albert@spenarnc.xs4all.nl>
Date2012-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]


#12636

FromArnold Doray <invalid@invalid.com>
Date2012-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]


#12637

FromAndrew Haley <andrew29@littlepinkcloud.invalid>
Date2012-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]


#12642

FromArnold Doray <invalid@invalid.com>
Date2012-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