Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Is using multiple EXITs bad programming practice?

25 views
Skip to first unread message

Brad Eckert

unread,
Jun 29, 1996, 3:00:00 AM6/29/96
to
I routinely use EXIT in my programming to avoid ugly control structures,
but some people consider it bad programming practice. Are there any good
reasons not to do so, or is it just a religious issue?

-- Brad


Zsoter Andras

unread,
Jun 29, 1996, 3:00:00 AM6/29/96
to

A religious issue.

Andras


JWillard44

unread,
Jun 29, 1996, 3:00:00 AM6/29/96
to
h929...@hkuxa.hku.hk (Zsoter Andras) wrote:
> A religious issue.

If you will forgive a Forth novice for speaking out...
In my experience, in many different languages that allow it, I have
often regretted more than one exit from a subroutine. The least problems
has been in Turbo Pascal which provides an Exit command. This is because
the Exit does all the built-in hand waving to restore conditions and
return to the calling routine.
The problem shows up when you have to go back and change the code to
correct a bug or update the program. It becomes all too easy to do
something newly required for one of the exits and miss the other exits.
The program now runs great until somebody hits the wrong key, or enters
bad data or something that you didn't test for and bingo, up crops the old
bug you thought you had fixed.
The solution to this is set up one exit point per routine with all
the processes you have to do upon exit (like set a flag, clear a portion
of the screen, etc.). Then, instead of exiting at alternate points, jump
to the exit code you have set up (if the language allows). That way if
you make changes, you make them only at one point and everything gets
changed.

Jonah Thomas

unread,
Jun 29, 1996, 3:00:00 AM6/29/96
to
In <4r2jqi$k...@newsbf02.news.aol.com> jwill...@aol.com (JWillard44) writes:

>h929...@hkuxa.hku.hk (Zsoter Andras) wrote:
>> A religious issue.

> If you will forgive a Forth novice for speaking out...

Sure!

> In my experience, in many different languages that allow it, I have
>often regretted more than one exit from a subroutine. The least problems
>has been in Turbo Pascal which provides an Exit command. This is because
>the Exit does all the built-in hand waving to restore conditions and
>return to the calling routine.

The problem may have been something other than the exits, perhaps?

> The problem shows up when you have to go back and change the code to
>correct a bug or update the program. It becomes all too easy to do
>something newly required for one of the exits and miss the other exits.
>The program now runs great until somebody hits the wrong key, or enters
>bad data or something that you didn't test for and bingo, up crops the old
>bug you thought you had fixed.

I think this is a conceptual problem, and no one solution works all the time.
If your code looks simple, it's easier to see whether you want the change in
all cases.

: TEST
CASE
1ST-CONDITION OF DO-1ST-THING ENDOF
2ND-CONDITION OF DO-2ND-THING ENDOF
3RD-CONDITION OF DO-3RD-THING ENDOF
;

If you can look at all three on three lines and see whether you want the
change every time, then you know you want it at the end.

: TEST1
1ST-CONDITION OVER = IF DO-1ST-THING EXIT THEN
2ND-CONDITION OVER = IF DO-2ND-THING EXIT THEN
3RD-CONDITION OVER = IF DO-3RD-THING EXIT THEN
;
: TEST
TEST1 CLEANUP
;

If you have multiple exits, you can wrap them very easily and handle it.

But if you have to reach deep into DO-2ND-THING to find the problem, it may
not be obvious that you want to change DO-1ST-THING & DO-3RD-THING too. When
all the code is right there in a giant routine, it's easy to get lost in it
and not even notice the other routines. When it's carefully factored into
short routines, it's easy to look at the innards of DO-2ND-THING and not even
notice that it's embedded inside a conditional at some higher level.

> The solution to this is set up one exit point per routine with all
>the processes you have to do upon exit (like set a flag, clear a portion
>of the screen, etc.). Then, instead of exiting at alternate points, jump
>to the exit code you have set up (if the language allows). That way if
>you make changes, you make them only at one point and everything gets
>changed.

What it takes is to notice the bigger context. Once you notice the general
problem, you can solve it somehow. But until you notice carefully, you might
not realize that you want the new thing in DO-2ND-THING & DO-3RD-THING but
_not_ DO-1ST-THING . You can get as many problems putting it at the end as
not. It depends on the problem, and on your noticing what it takes to solve
it.

When it's a complicated problem, no simple idea about structure will solve
it. You have to actually deal with the complications, and that can be a
complicated process. I think it's usually good for the code to be organized
in a way that naturally fits the particular problem. If you can use your
knowledge about how the problem ( or the solution?) is organized to help you
keep track of the program, that's a plus. But doing that seems to be an art
that again doesn't just use simple rules.

You can rearrange so that DO-2ND-THING & DO-3RD-THING are together, and you
can put your solution after them. But then what do you do if you need to
make another change, and that one affects DO-1ST-THING & DO-2ND-THING but
_not_ DO-3RD-THING ? You can make the change in 2 places, or you can pass
some kind of flag to say whether to do it. Or you can look at the problem at
a lower level, and maybe restructure it some new way. That last might be
good in the long run, you might be able to make your code simpler and easier
to follow and better match the problem, and other simplifications could fall
out of it in the process. But it will probably take a lot of retesting.

If you had an efficient way to test all the cases, that would help a lot.
But how can you design the tests before you know how you'll split up the
problem? Designing all the tests for the final application is likely to be
tremendously complex for a complicated problem, but if you design simpler
tests for each section, you'll have to revise the tests every time you reform
the structure.

I dunno.


Zsoter Andras

unread,
Jun 29, 1996, 3:00:00 AM6/29/96
to
JWillard44 (jwill...@aol.com) wrote:
>h929...@hkuxa.hku.hk (Zsoter Andras) wrote:
>> A religious issue.

> The problem shows up when you have to go back and change the code to


>correct a bug or update the program. It becomes all too easy to do
>something newly required for one of the exits and miss the other exits.

If you have such a problem then your program is hmm, "not very well factored".
If you have to restore things before your exit, you better break up
the definition/function/procedure/subroutine to smaller ones.
I can write Forth programs in Turbo Pascal. ;-)

> The solution to this is set up one exit point per routine with all
>the processes you have to do upon exit (like set a flag, clear a portion
>of the screen, etc.). Then, instead of exiting at alternate points, jump
>to the exit code you have set up (if the language allows). That way if
>you make changes, you make them only at one point and everything gets
>changed.

Should we reinvent GOTO for this purpose or a fifty-level-deep nested
spaghetti of IF THEN -s would do? ;-)

Andras


Elizabeth Rather

unread,
Jun 29, 1996, 3:00:00 AM6/29/96
to
JWillard44 wrote:
>
> h929...@hkuxa.hku.hk (Zsoter Andras) wrote:
> > A religious issue.
>
> If you will forgive a Forth novice for speaking out...
> In my experience, in many different languages that allow it, I have
> often regretted more than one exit from a subroutine.

The principles of "structured programming" as enunciated by Djkstra and followers
in the early '70s include the principle that a routine should have one entrance
and one exit. This is widely accepted as a guideline that will help produce more
reliable, more maintainable code regardless of language.

In Forth, "good style" tends to emphasize very short, clean words; an extremely
high degree of modularity. In languages such as Fortran and C "short" tends to
mean about a page; in Forth "short" means 2-3 _lines_, and in fact the majority of
our code is this modular! When followed, this style also contributes reliability
and maintainability, and also reduces the temptation toward multiple exits (which
tend to occur in long-winded "spaghetti code").

--
Elizabeth D. Rather
FORTH, Inc. Products and services for
111 N. Sepulveda Blvd. professional Forth programmers
Manhattan Beach, CA 90266 since 1973. See us at:
310-372-8493/fax 318-7130 http://www.forth.com

RICHARD ASTLE

unread,
Jun 29, 1996, 3:00:00 AM6/29/96
to

For many it's a religious issue. I think, however, anything that produces
clarity is worth using. I couple EXIT with a word I call RETRY, which is its opposite,
i.e., it goes back to the beginning of the current colon definition and starts
again--sort of like a REPEAT or an AGAIN with an implicit BEGIN, or a RECURSE without
nesting. For me this makes many words simpler, reducing indentation and stack flag
juggling, and makes these words like nice little well-factored machines. In fact, using
RETRY and EXIT in a word forces you to factor it so that it will work (i.e., you leave
anything before the implied BEGIN or after the implied REPEAT in the enclosing calling
word), a factoring discipline I now find natural, useful, and pleasing.
The shortcoming of this technique is that there is probably no way to define
RETRY in ANS Forth.
I wrote a short article on this subject that was published in Forth Dimensions
XVII, number 4, November-December 1995.

Richard
ras...@ix.netcom.com

Ras...@ix.netcom.com

unread,
Jun 29, 1996, 3:00:00 AM6/29/96
to

From: RICHARD ASTLE <ras...@ix.netcom.com>
Subject: Re: Is using multiple EXITs bad programming practice?
Organization: Netcom

Richard
ras...@ix.netcom.com
--
|Fidonet: Ras...@ix.Netcom.Com 1:377/51.2
|Internet: Ras...@ix.Netcom.Com
|
| Standard disclaimer: The views of this user are strictly his own.


Jonah Thomas

unread,
Jun 30, 1996, 3:00:00 AM6/30/96
to

In <31D574...@ix.netcom.com> RICHARD ASTLE <ras...@ix.netcom.com>
writes:
>I couple EXIT with a word I call RETRY, which is its opposite, i.e.,
>it goes back to the beginning of the current colon definition and
>starts again--sort of like a REPEAT or an AGAIN with an implicit
>BEGIN, or a RECURSE without nesting. For me this makes many words
>simpler, reducing indentation and stack flag juggling, and makes these
>words like nice little well-factored machines. In fact, using RETRY
>and EXIT in a word forces you to factor it so that it will work (i.e.,
>you leave anything before the implied BEGIN or after the implied
>REPEAT in the enclosing calling word), a factoring discipline I now
>find natural, useful, and pleasing.

> The shortcoming of this technique is that there is probably no
>way to define RETRY in ANS Forth.

That doesn't look hard to me, given the tricks Wil Baden showed us for
CASE .

VARIABLE CS-DEPTH
: IF 1 CS-DEPTH +! POSTPONE IF ; IMMEDIATE
: THEN -1 CS-DEPTH +! POSTPONE THEN ; IMMEDIATE
: BEGIN 1 CS-DEPTH +! POSTPONE BEGIN ; IMMEDIATE
: WHILE 1 CS-DEPTH +! POSTPONE WHILE ; IMMEDIATE
: UNTIL -1 CS-DEPTH +! POSTPONE UNTIL ; IMMEDIATE
: REPEAT -2 CS-DEPTH +! POSTPONE REPEAT ; IMMEDIATE

: :RETRYABLE 0 CS-DEPTH ! : ;
( depends on : not being immediate, else do POSTPONE : )
: DOES>RETRYABLE 0 CS-DEPTH ! POSTPONE DOES> ; IMMEDIATE

: ;RETRYABLE -1 POSTPONE LITERAL POSTPONE UNTIL POSTPONE ; IMMEDIATE

: RETRY CS-DEPTH CS-PICK 0 POSTPONE LITERAL POSTPONE UNTIL ; IMMEDIATE

This doesn't let you RETRY out of a DO LOOP. Provided that you can
CS-PICK past a do-sys, you can do that too.

VARIABLE DO-DEPTH
: DO 1 CS-DEPTH +! 1 DO-DEPTH +! POSTPONE DO ; IMMEDIATE
: LOOP -1 CS-DEPTH +! -1 DO-DEPTH +! POSTPONE LOOP ; IMMEDIATE
: +LOOP -1 CS-DEPTH +! -1 DO-DEPTH +! POSTPONE +LOOP ; IMMEDIATE

: :RETRYABLE 0 CS-DEPTH ! 0 DO-DEPTH ! : ;
: :NONAME-RETRYABLE 0 CS-DEPTH ! 0 DO-DEPTH ! POSTPONE :NONAME ; IMMEDIATE
: DOES>RETRYABLE 0 CS-DEPTH ! 0 DO-DEPTH ! POSTPONE DOES> ; IMMEDIATE

: RETRY
DO-DEPTH @ 0 ?DO POSTPONE UNLOOP LOOP
POSTPONE RETRY ; IMMEDIATE

This code hasn't been tested, but it looks so straight-forward that I'm
confident something similar would actually work.

Required:
CS-PICK
?DO


Richard Astle

unread,
Jul 1, 1996, 3:00:00 AM7/1/96
to


My familiarity with ANS Forth is not as great as it should be, since I do my daily work
in a dialect descended from MVP-Forth through Pierre Moreton and modified by me to be
nearly 83-Standard. The Neil Bawd inspired implementation of RETRY suggested here
however seems not to be quite what I had in mind. Namely, it apparently needs a special
version of colon, rather than allowing a RETRY in ANY word, and it wouldn't seem to
allow multiple RETRYs within a single colon definition, making it not a good opposite of
EXIT. My usual implementation, ALMOST 83-Standard, is

: RETRY LATEST NAME> >BODY COMPILE BRANCH <RESOLVE ; IMMEDIATE
or
: RETRY LATEST NAME> >BODE 1 [COMPILE] AGAIN ; IMMEDIATE

in a Forth with so-called "compiler security". In LMI WinForth the following work:

: RETRY ?COMP LAST @ N>BODY 1 [COMPILE] AGAIN ; IMMEDIATE
: RETRY ?COMP LAST @ N>BODY COMPILE branch HERE - , ; IMMEDIATE

My belief, about which I would be happy to be proven wrong, that RETRY cannot be defined
within an ANS Forth is based on the difficulty of imagining a definition for RECURSE in
that standard if RECURSE were not already required.

Jonah Thomas

unread,
Jul 2, 1996, 3:00:00 AM7/2/96
to

In <31D89A...@ix.netcom.com> Richard Astle <ras...@ix.netcom.com> writes:

>Jonah Thomas wrote:

>> That doesn't look hard to me, given the tricks Wil Baden showed us for
>> CASE .

[code snipped]

>The Neil Bawd inspired implementation of RETRY suggested here
>however seems not to be quite what I had in mind. Namely, it apparently
needs a special
>version of colon, rather than allowing a RETRY in ANY word, and it wouldn't
seem to
>allow multiple RETRYs within a single colon definition, making it not a good
opposite of
>EXIT.

You could redefine : instead of naming it :RETRYABLE . There's a slight
execution penalty and I didn't want to incur that in every word whether I
used it or not. But you could, no problem. It _does_ allow multiple RETRYs.
The point is the CS-PICK which copies the item that the starting BEGIN made
and does a new UNTIL each time. You can do it as many times as you want to.


>I would be happy to be proven wrong, that RETRY cannot be defined
>within an ANS Forth is based on the difficulty of imagining a definition for
RECURSE in
>that standard if RECURSE were not already required.

RECURSE is harder. I'm not sure how to do that. The trouble is, there's no
standard way to get the xt of the current definition before the definition is
finished. RECURSE keeps you from _having_ to get the xt, but it still
doesn't give you a way to do it. That's a tough one. You could get an
address and @ an xt from it and EXECUTE it every time you want to do RECURSE
and then after the definition is finished put its xt into the address. Or
there might be some better way. Hmm. I'm not sure all the usual ways to do
RECURSE will work with :NONAME . That's something to watch out for if you
write a standard compiler.


Elizabeth Rather

unread,
Jul 2, 1996, 3:00:00 AM7/2/96
to

Jonah Thomas wrote:

> RECURSE is harder. I'm not sure how to do that.

The reason RECURSE is in the CORE is that there is no guaranteed way to write it,
nor did the TC feel it desirable to be able to do so. In fact, the dividing line
between the CORE and other wordsets (such as CORE EXT) is that the CORE words may
not be implementable in high level (or it may be undesirable to do so, for
example for performance reasons). In fact, IMO it doesn't make sense to fuss
about how to write CORE words standardly, because any "standard system" you might
try to port this stuff to by definition already has them!

> That's something to watch out for if you write a standard compiler.

A "standard system" already has a compiler.

Jonah Thomas

unread,
Jul 3, 1996, 3:00:00 AM7/3/96
to

In <31D93D...@forth.com> Elizabeth Rather <era...@forth.com>
writes:

>Jonah Thomas wrote:

<snip>

> IMO it doesn't make sense to fuss
>about how to write CORE words standardly, because any "standard system"
>you might try to port this stuff to by definition already has them!

It's an academic exercise, of no immediate economic value. If you can
write some CORE words using other CORE words then you can have a smaller
kernel of primitives. The smaller the set of primitives you have to
write, the quicker you can get your standard system running on new
hardware (and probably the slower it will run).

Also, if you write a CORE word in ANS Forth you're providing a kind of
definition for the word, in Forth instead of in English. The question
arises whether the Forth definition is correct. Does it have side
effects or depend on some behavior that isn't guaranteed? Is there
another legal way to write it that isn't equivalent? People who like
that sort of thing can spend pleasant Sunday afternoons playing with it,
a game that's certainly no worse than crossword puzzles. It could be
argued that they should spend their time doing something productive
instead, but we can't all be productive all the time.

>> That's something to watch out for if you write a standard compiler.

>A "standard system" already has a compiler.

I meant that people who write standard systems should notice whether
they're making RECURSE work correctly with :NONAME definitions. Some of
the obvious approaches won't work with that.


Richard Astle

unread,
Jul 3, 1996, 3:00:00 AM7/3/96
to

Elizabeth Rather wrote:
>
> Jonah Thomas wrote:
>
> > RECURSE is harder. I'm not sure how to do that.
>
> The reason RECURSE is in the CORE is that there is no guaranteed way to write it,
> nor did the TC feel it desirable to be able to do so. In fact, the dividing line
> between the CORE and other wordsets (such as CORE EXT) is that the CORE words may
> not be implementable in high level (or it may be undesirable to do so, for
> example for performance reasons). In fact, IMO it doesn't make sense to fuss

> about how to write CORE words standardly, because any "standard system" you might
> try to port this stuff to by definition already has them!
>
> > That's something to watch out for if you write a standard compiler.
>
> A "standard system" already has a compiler.
>
> --
> Elizabeth D. Rather
> FORTH, Inc. Products and services for
> 111 N. Sepulveda Blvd. professional Forth programmers
> Manhattan Beach, CA 90266 since 1973. See us at:
> 310-372-8493/fax 318-7130 http://www.forth.com

Part of this was pretty much my point (about the difficulty of defining RETRY
standardly). If RECURSE weren't in the standard it might well be that there would be no
way to have it in a standard system. I was afraid the same would be true for RETRY,
which I have been using and found useful (in my feeling it and EXIT together provide
better modularity in at least many cases) for years. To my perhaps peculiar way of
thinking its worth is so obvious that if it had been presented to the Standards
committee it would perforce have been adopted, and I regretted not springing it on the
world until it was too late.
Jonah Thomas may have freed me from this regret with his solution, which I've
not yet tested. (He suggests one might redefine : to leave something useful on the
control stack, though he himself would prefer not to.) He does point out that there
would be a slight execution penalty for a redefined : (or would this only affect compile
time?).
Given this (as yet untested, by me at least) possible standard
solution to the definition of RETRY, would a system be considered standard that included
a perhaps more efficient RETRY defined in terms of implementation dependent,
non-standard primitives? My hazy memory of the 83-Standard was that all you had to
provide to make a program standard was standard definitions of all non-standard words.
The implication I got there was that you didn't actually have to define your
non-standard words in terms of standard words, only show that it was possible to do so.

Richard Astle
ras...@ix.netcom.com

Jonah Thomas

unread,
Jul 3, 1996, 3:00:00 AM7/3/96
to

In <31DA1A...@ix.netcom.com> Richard Astle <ras...@ix.netcom.com>
writes:

> If RECURSE weren't in the standard it might well be that there
would be no
>way to have it in a standard system. I was afraid the same would be true
for RETRY,
>which I have been using and found useful (in my feeling it and EXIT
together provide
>better modularity in at least many cases) for years. To my perhaps
peculiar way of
>thinking its worth is so obvious that if it had been presented to the
Standards
>committee it would perforce have been adopted, and I regretted not
springing it on the
>world until it was too late.

They're probably going to start up the standards effort again soon. I doubt
that they'll seriously consider an idea which is so little-used, but you
don't have much to lose by finding out. The more people you can persuade to
try it out, the better the chances.

> Jonah Thomas may have freed me from this regret with his solution,
which I've
>not yet tested. (He suggests one might redefine : to leave something
useful on the
>control stack, though he himself would prefer not to.) He does point out
that there
>would be a slight execution penalty for a redefined : (or would this only
affect compile
>time?).

It would affect execution time. Every command using the redefined : would
have an extra BEGIN -1 UNTIL loop that it would go through at least once.
That means at a minimum an extra literal and an extra failed branch.

> Given this (as yet untested, by me at least) possible standard
>solution to the definition of RETRY, would a system be considered standard
that included
>a perhaps more efficient RETRY defined in terms of implementation
dependent,
>non-standard primitives? My hazy memory of the 83-Standard was that all
you had to
>provide to make a program standard was standard definitions of all
non-standard words.

I think so. Any program that you'd want to be standard would need to
include the redefined : as part of a preamble, at least until the code got
included in some commonly-used library. I think you'd still have a standard
system even after you redefined : this way, but I'm not absolutely certain.
Someone else might want to redefine : some other way which might be somehow
incompatible, and they could argue that a standard : should work for them,
and be right. I don't have an example of a problem like that, but I don't
know for sure that there can't be one.

>The implication I got there was that you didn't actually have to define
your
>non-standard words in terms of standard words, only show that it was
possible to do so.

Yes. And remember, the _system_ that includes your RETRY can be standard
and still include RETRY . A standard system can do all sorts of extra
things provided it does the standard things too and the standard things work
together the way they're supposed to. The problem is that standard
_programs_ can't use the extra things and still be portable. If you can fix
up standard systems using standard code so they run your program, then your
program is portable.


Elizabeth Rather

unread,
Jul 3, 1996, 3:00:00 AM7/3/96
to

Richard Astle wrote: [regarding RETRY]

> Given this (as yet untested, by me at least) possible standard
> solution to the definition of RETRY, would a system be considered standard that included
> a perhaps more efficient RETRY defined in terms of implementation dependent,
> non-standard primitives?

Insofar as RETRY is a non-standard extension, you can provide any extensions you want to and
still be a standard system. A standard program may not use such extensions without
declaring a dependency on them.

> My hazy memory of the 83-Standard was that all you had to
> provide to make a program standard was standard definitions of all non-standard words.

> The implication I got there was that you didn't actually have to define your
> non-standard words in terms of standard words, only show that it was possible to do so.

It is only necessary to provide definitions for the "missing" words (or standard variants
thereof), not that those definitions be themselves in terms of standards words. The
assumption is that if they are CORE words it _may_not_be_possible_ to define them in terms
of standard words.

M.L.Gassanenko

unread,
Jul 4, 1996, 3:00:00 AM7/4/96
to

> The problem shows up when you have to go back and change the code to
> correct a bug or update the program. It becomes all too easy to do
> something newly required for one of the exits and miss the other exits.

In just a few words:

Normally Forth procedures (words) are so small that you see all the exits
on the same screen, and therefore you do not have this problem.

BUT: if you introduce additional branches and let your words grow and grow,
this *is* bad programming, regardless of the use of exits in the branches.

When there are *really* many branches, it is convenient to terminate them by
EXITs. In these sases your use the "EXIT THEN" idiom and also have
no problems (BUT: when you work with such words, check that all IFs
are balanced with "EXIT THEN"s -- the compiler cannot catch this error).

Resume: indeed, misused exits are bad practice---just as any misuses.
The problem is not in exits but in ability to keep code simple while
maintaining/modifying it.

---
M.L.Gassanenko
m...@iias.spb.su g...@agspbu.spb.su

ray.fe...@gpo.canada.cdev.com

unread,
Jul 11, 1996, 3:00:00 AM7/11/96
to

> Should we reinvent GOTO for this purpose or a fifty-level-deep nested
> spaghetti of IF THEN -s would do? ;-)
>

I can't reconcile a disdain for GOTO in a language aimed at hackers!

RayF

Mike Coughlin

unread,
Jul 12, 1996, 3:00:00 AM7/12/96
to

In article <31D93D...@forth.com>,

Elizabeth Rather <era...@forth.com> wrote:
>Jonah Thomas wrote:

>> RECURSE is harder. I'm not sure how to do that.

>The reason RECURSE is in the CORE is that there is no guaranteed
>way to write it, nor did the TC feel it desirable to be able to
>do so. In fact, the dividing line between the CORE and other
>wordsets (such as CORE EXT) is that the CORE words may not be
>implementable in high level (or it may be undesirable to do so, for
>example for performance reasons). In fact, IMO it doesn't make
>sense to fuss about how to write CORE words standardly, because
>any "standard system" you might try to port this stuff to by
>definition already has them!

>> That's something to watch out for if you write a standard compiler.

>A "standard system" already has a compiler.

When I first started studing Mathematics and Physics as a
teenager, I wondered why it was required to derive equations.
Hadn`t these things been proven years ago, and why did I have to
know how to do it all over again? I found out that you couldn't
really understand Math and Physics unless you could derive the
equations. In the same way, I don't think it is possible to really
understand any version of Forth unless you write your own version
or rederive someone else's. Doing this might not produce a
commercial version of Forth, but you will learn how to select the
best commercial version for your needs and how to use it
effectively. Forth can be used well without knowing how to write
your own version, but the best Forth programmers seem to be the
ones who have learned how to write the whole system.

--
Michael Coughlin mi...@gnu.ai.mit.edu Cambridge, MA USA

Jonah Thomas

unread,
Jul 12, 1996, 3:00:00 AM7/12/96
to

In <4s5hcl$l...@life.ai.mit.edu> mi...@gnu.ai.mit.edu (Mike Coughlin)
writes:

>>> RECURSE is harder. I'm not sure how to do that.

It turns out that RECURSE isn't that hard to write using only other
standard Forth words. It isn't particularly important to do that since
it's present in all standard systems anyway, but the technique might
possibly be useful for something else.


David Melton

unread,
Jul 12, 1996, 3:00:00 AM7/12/96
to

ray.fe...@gpo.canada.cdev.com wrote:
: > Should we reinvent GOTO for this purpose or a fifty-level-deep nested

: > spaghetti of IF THEN -s would do? ;-)

If someone's implying that a few GOTOs would resolve a very deep nesting
problem, they probably qualify as one of the "hackers" mentioned below.
My initial suspicion would be that if it looked like those were the only
choices (or if I saw a piece of code using one of those techniques),
that there is almost certainly a design or factoring problem.

Within a properly designed/factored word, the indentation of the
nested conditionals provides immensely valuable visual clues to
the operation of the word. You do indent, don't you ??? A big mess
of GOTOs is much harder to read, and further encourages poor
design and coding practices. Also, it's much harder to document
the program flow through a tangled mass of GOTOs, which complicates
development of thorough test conditions.

I guess you can probably figure where I think GOTO should GOTO...<g>


: I can't reconcile a disdain for GOTO in a language aimed at hackers!

: RayF

Ray, this is either a troll of the highest order, or a serious
misconception. In any case, I'll byte.....

Forth certainly encourages a more iterative programming approach
than most other languages. When properly applied, this is a
powerful tool for prototyping, debugging, hardware validation,
and so on. But, not unlike tequila and sportscars, abuse of a
good thing can be dangerous!

As far as "code quality", it's quite possible to write very good
or very bad code in just about any language. I've written
systems with several thousand of lines of assembly code that are
neat, well organized, and readable by someone other than me.
Likewise with C, Forth, and other languages. On the other hand,
I've seen plenty of code in each of these environments that was
such a mess that the original programmer couldn't even maintain it.

Undisciplined programming and (lack of) design are in no way
unique to the Forth community. Even if Forth developers wrote
demonstrably "worse" code by whatever metric, anyone encouraging
good programming practices (like avoiding GOTO) should be
encouraged, not insulted.

(Sorry for the edgy tone, but I'm starting work on a project
converting a bunch of cryptic, undocumented, and generally
nasty-looking C code (yuck), mostly into Forth (yippee!). The
last thing I want to hear is someone implying that I'm a
"hacker by association" because I'm part of the Forth community!)

Anyway, back at it.......

Dave


Norman L. DeForest

unread,
Jul 12, 1996, 3:00:00 AM7/12/96
to

Mike Coughlin (mi...@gnu.ai.mit.edu) wrote:
: When I first started studing Mathematics and Physics as a

: teenager, I wondered why it was required to derive equations.
: Hadn`t these things been proven years ago, and why did I have to
: know how to do it all over again? I found out that you couldn't
: really understand Math and Physics unless you could derive the
: equations. In the same way, I don't think it is possible to really
: understand any version of Forth unless you write your own version
: or rederive someone else's. Doing this might not produce a
: commercial version of Forth, but you will learn how to select the
: best commercial version for your needs and how to use it
: effectively. Forth can be used well without knowing how to write
: your own version, but the best Forth programmers seem to be the
: ones who have learned how to write the whole system.

I agree. I have written a version of (almost) FORTH-83 for my Texas
Instruments Professional with nothing to go on but some notes on LMI FORTH
obtained a few years earlier when an acquaintance asked me to determine
how to use his newly acquired FORTH after a fire destroyed his
documentation and the address of Laboratory Microsystems Inc. as well.

It only required some minor changes, for hardware reasons, to compile
several source files available in some of my back-issue magazines.

I find it much easier to understand ANY system after trying to duplicate
or reverse engineer it.

Norman De Forest
af...@ccn.cs.dal.ca
http://www.ccn.cs.dal.ca/~af380/Profile.html

--

Albert Lee Mitchell

unread,
Jul 13, 1996, 3:00:00 AM7/13/96
to

ray.fe...@gpo.canada.cdev.com wrote:
>
> > Should we reinvent GOTO for this purpose or a fifty-level-deep nested
> > spaghetti of IF THEN -s would do? ;-)
> >
>
> I can't reconcile a disdain for GOTO in a language aimed at hackers!
>
> RayF

Why not use Catch and Throw to unnest?

-- Albert

----------------------------------------------------------------------
AM Research, the Embedded Control Experts. http://www.amresearch.com
----------------------------------------------------------------------

Dwight Elvey

unread,
Jul 15, 1996, 3:00:00 AM7/15/96
to

I think that if you are seeing many nested IF-ELSE-THEN's
you should either factor more or if one is doing the
IF's on the same subject, replace it with something
like a table look up. I've only had the need to use
EXIT in about two or three words that I can remember.
Even in these cases, I could have done it without
the EXIT, it's just that it was even messier. Like >R
and R>, EXIT is good when used carefully.
IMHO
Dwight

Andrew McKewan

unread,
Jul 15, 1996, 3:00:00 AM7/15/96
to

I agree that structured conditionals are easier to read than programming
with gotos, there are times when a goto can make code more efficient and
easier to read. Of course, we do not have gotos in standard Forth.


----------------------------------------------------------------------
Andrew McKewan mck...@austin.finnigan.com
Finnigan Corporation
2215 Grand Avenue Parkway Tel: (512) 251-1574
Austin, TX 78728-3812 Fax: (512) 251-1547

Elizabeth Rather

unread,
Jul 15, 1996, 3:00:00 AM7/15/96
to

Albert Lee Mitchell wrote:
> > > Should we reinvent GOTO for this purpose or a fifty-level-deep nested
> > > spaghetti of IF THEN -s would do? ;-)
> >
> > I can't reconcile a disdain for GOTO in a language aimed at hackers!
>
> Why not use Catch and Throw to unnest?

CATCH and THROW are great for error handling, but are not designed to support
logical control in the absence of good factoring! We ran into this problem in
our recent credit card terminal prototypes, where some team members used
these words in this way and built some very unmaintainable structures.

-------

Elizabeth Rather

unread,
Jul 17, 1996, 3:00:00 AM7/17/96
to

Paul Shirley wrote:
> Even the most die hard anti GOTO bigots sometimes agree its pretty
> useful in error recovery. So useful that civilized languages support
> GOTO as 'exceptions' (new name, restricted uses but its still just a
> GOTO)
>...
> I've only ever done it in error recovery (restarting loops usually,
> thought I did once unwind the stack in asm to skip code in one step
> rather than add an IF at all levels of nesting)

Yes, the Forth adaptation for this purpose is CATCH/THROW!

--

Richard Astle

unread,
Jul 17, 1996, 3:00:00 AM7/17/96
to

Chris Gray wrote:

> It looks to me as though CATCH and THROW should also be useful for
> implementing algorithms of a "branch&bound" nature, where one often
> needs to be able to discard a variable amount of accumulated state.
> Structured-programming implementation of such an algorithm tends to
> mean implementing one's own stack, which feels a bit silly.

I've been using a version of CATCH and THROW for years, ever since Mike Perry
described Mitch Bradley's implementation at a FORML conference whose date I've
forgotten. The idea seemed so useful to me (I'd heard of the LISP version, but hadn't
grasped it) that I implemented that weekend, even before going home, and completely
ignored its intended use for error handling. My first use of it was in a menu system.
I tied THROW to Escape key, allowing immediate return to the top level menu from
whatever menu depth. The problem I had was the number of things I had to unroll. THROW
-> CATCH in its bare implementation just pealed back the return and parameter stacks,
but I also had a menu stack, a window buffer stack, a database file stack, an overlays
stack, maybe more. Without getting into details of these things, I'll just say that
this complexity encouraged me to keep the implementation of CATCH and THROW at a fairly
high level, after all those other stacks of things were defined, so I could throw
pointers to them on the return stack along with the parameter stack pointer in CATCH.
Thus it's not the ANS version. Also, I found I needed an enormous return stack.

In other places, I found myself passing things up through levels of CATCH and
THROW, sometimes with an idiom like the following:

set-some-vector
['] DOG CATCH
restore-the-vector
?DUP IF THROW THEN

An idiom like this can unwind things that don't have stacks, and therefore don't have
stack pointers to store on the return stack.

Actually, I imagine this kind of use of CATCH and THROW must be familiar to
anyone who has used the words much, so I don't know if I'm contributing to anyone's
clarity here. So be it.

ras...@ix.netcom.com

Chris Gray

unread,
Jul 17, 1996, 3:00:00 AM7/17/96
to

In article <31E9E1...@forth.com>, Elizabeth Rather <era...@forth.com> writes:
>
>CATCH and THROW are great for error handling, but are not designed to support
>logical control in the absence of good factoring! We ran into this problem in
>our recent credit card terminal prototypes, where some team members used
>these words in this way and built some very unmaintainable structures.
>

It looks to me as though CATCH and THROW should also be useful for


implementing algorithms of a "branch&bound" nature, where one often
needs to be able to discard a variable amount of accumulated state.
Structured-programming implementation of such an algorithm tends to

mean implementing one's own stack, which feels a bit silly. Does
FORTH, Inc. have any experience of using CATCH and THROW in this
context?

My experience in block-structured languages is that multiple exits tend
to throw up just as many problems as deeply nested conditionals: missing
clean-up actions, unassigned outputs, the whole sad litany. By the time
I've satisfied myself that an early exit is completely kosher, I've
factored the problem to a point where in FORTH I'd probably make two
words of it.

--
__________________________________________________________________________

Chris Gray Chris...@bcs.org.uk Compuserve: 100065,2102
__________________________________________________________________________


Ed Borasky

unread,
Jul 17, 1996, 3:00:00 AM7/17/96
to

Quoth the Chris Gray (gr...@btmaa.bel.alcatel.be):

>It looks to me as though CATCH and THROW should also be useful for
>implementing algorithms of a "branch&bound" nature, where one often
>needs to be able to discard a variable amount of accumulated state.
>Structured-programming implementation of such an algorithm tends to
>mean implementing one's own stack, which feels a bit silly. Does
>FORTH, Inc. have any experience of using CATCH and THROW in this
>context?

Don't forget that you have recursion available in ANS Forth as well. Many
of the "traditional" operations research procedures have natural recursive
formulations. The ANS specification of CATCH and THROW reserves a small
number of negative values for system-wide error conditions such as
floating-point stack underflow. I believe that all 32766 *positive* numbers
(on a 16-bit system) are available for user THROW codes. If you want to
experiment with this, pick up hForth from the Taygeta archive. Tom Almy's
shareware ForthCMP 2.3S (the ANS version) also implements CATCH and THROW.

One other note: both ForthCMP and hForth have multitaskers, which is another
structuring tool for OR problems. I haven't compared them to see how the
syntax and semantics compare, though, so you might need to have two versions of
your code.

--
M. Edward Borasky

The American people are tired of being told what the American people
are tired of.

Gary I Ellis

unread,
Jul 17, 1996, 3:00:00 AM7/17/96
to

I was hoping to stay out of this one :-)

However noone's mentioned what I consider one of the fundamentals of good
design, namely that each module should have one (and only one) entry point and
one (and only one) exit point.

Therefore on the face of it requirement for multiple exit points in the *design*
is a bad thing.

However I have frequently found when implementing, that "while" loops used for
list searches and the like are naturally terminated by one of two conditions,
i.e. reaching the end of the list, or finding what you were looking for. In
these sorts of cases, the judicious use of an exit can simplify an otherwise
ugly/complex/bad piece of code.

With that one exception, (and error handlers which are a special case anyway)
I've yet to find the need to code more than one exit point. If I find myself in
this position I have always been able to cure it with better factorisation or a
rationalisation of the original design.


Gary I Ellis - Control Systems S/W Engineer | Shirley, Southampton, England
Business: g...@mpeltd.demon.co.uk | Phone/Fax +44 (1703) 332188
Personal: ga...@tcp.co.uk |
WWW: http://www.tcp.co.uk/~garye | Quote temporarily out to lunch


Anton Ertl

unread,
Jul 18, 1996, 3:00:00 AM7/18/96
to

In article <X82ChCAi...@chocolat.foobar.co.uk>, Paul Shirley <Pa...@chocolat.foobar.co.uk> writes:
|> Even the most die hard anti GOTO bigots sometimes agree its pretty
|> useful in error recovery.

Talk with Dijkstra about it. I'm sure he will not agree.

|> So useful that civilized languages support
|> GOTO as 'exceptions' (new name, restricted uses but its still just a
|> GOTO)

While exceptions are used for the same purpose that were the last
refuges of GOTO, they are quite different from GOTOs:

A GOTO has a fixed target, and is usually restricted to targets within
the current definition (or, in languages that allow nesting of
definitions, to outer definitions). The target of a THROW is not fixed
at compile time (in general); it is the dynamically next outer
CATCH. In one instance a THROW can have one CATCH as target, in
another instance a completely different CACTH.

BTW, we have exceptions in Forth, too.

- anton
--
M. Anton Ertl Some things have to be seen to be believed
an...@mips.complang.tuwien.ac.at Most things have to be believed to be seen
http://www.complang.tuwien.ac.at/anton/home.html

Chris Gray

unread,
Jul 18, 1996, 3:00:00 AM7/18/96
to

In article <4sjevm$1...@zeus.tcp.co.uk>, ga...@tcp.co.uk (Gary I Ellis) writes:
>I was hoping to stay out of this one :-)
>
>However noone's mentioned what I consider one of the fundamentals of good
>design, namely that each module should have one (and only one) entry point and
>one (and only one) exit point.
>
>Therefore on the face of it requirement for multiple exit points in the *design*
>is a bad thing.
>

What is being debated here is whether the one-entry-one-exit really is
as fundamental as you say. Your fundamentals are under attack. :)

Bernd Paysan

unread,
Jul 18, 1996, 3:00:00 AM7/18/96
to

In article <31E9E1...@forth.com> Elizabeth Rather <era...@forth.com> writes:

Albert Lee Mitchell wrote:
> > > Should we reinvent GOTO for this purpose or a fifty-level-deep nested
> > > spaghetti of IF THEN -s would do? ;-)
> >
> > I can't reconcile a disdain for GOTO in a language aimed at hackers!
>
> Why not use Catch and Throw to unnest?

CATCH and THROW are great for error handling, but are not designed to support

logical control in the absence of good factoring! We ran into this problem in
our recent credit card terminal prototypes, where some team members used
these words in this way and built some very unmaintainable structures.

Complicated state machines should be handled with a state machine
generator, thus a dispatch routine that goes through a table. As Forth
is a very extensible language, it is not too hard (compared with the
rest of the problem) to build such a state machine generator. I saw
something like this in ComForth for Windows, which has "WHEN"-Lists
for event processing. In fact, a state-machine generator could use
such "WHEN"-lists to generate the state machine. E.g. you say

:noname keep-card ." Your card is kept because " .reason cr
." Please contact your credit institute" cr terminate ;
3-times-pid-wrong WHEN card-is-locked OR-WHEN

:noname start-transaktion;
pid-ok WHEN

:noname output-money ;
transaktion-ok WHEN
--
Bernd Paysan
"Late answers are wrong answers!"
http://www.informatik.tu-muenchen.de/~paysan/

Jonah Thomas

unread,
Jul 19, 1996, 3:00:00 AM7/19/96
to

In <4si9j3$j...@btmpjg.god.bel.alcatel.be> gr...@btmaa.bel.alcatel.be
(Chris Gray) writes:

>It looks to me as though CATCH and THROW should also be useful for
>implementing algorithms of a "branch&bound" nature, where one often
>needs to be able to discard a variable amount of accumulated state.
>Structured-programming implementation of such an algorithm tends to
>mean implementing one's own stack, which feels a bit silly. Does
>FORTH, Inc. have any experience of using CATCH and THROW in this
>context?

The problem I have with it is that when you THROW out of a deeply-nested
routine, you can't depend on anything you find on the stack except the
throw code. "Really", you know exactly what your routine has done to the
stack and you know exactly what CATCH and THROW have done. There was only
one place your routine could THROW from for each throw code, and you know
precisely what to expect from each one. You know that if some other
command calls your code, no deep stack items that your code is supposed to
ignore, will be affected by a THROW . But I'm just not completely
convinced. I only feel comfortable doing CATCH THROW for non-error
conditions, when the stack comes out _empty_. And if I can't leave
anything on the stack when I call a routine, I'd rather rewrite it
instead.

If you're closing down from an error, it isn't such a problem. But maybe
this is just due to my relative inexperience. Maybe when I've seen how a
lot of Forth systems implement CATCH and THROW I'll trust them to leave my
stacks alone.

>My experience in block-structured languages is that multiple exits tend
>to throw up just as many problems as deeply nested conditionals: missing
>clean-up actions, unassigned outputs, the whole sad litany. By the time
>I've satisfied myself that an early exit is completely kosher, I've
>factored the problem to a point where in FORTH I'd probably make two
>words of it.

If you can split it into multiple words, why not just do that instead of
agonizing over multiple exits?


john wavrik

unread,
Jul 19, 1996, 3:00:00 AM7/19/96
to


In Article 24947 of comp.lang.forth:
Ed Borasky writes:

> Don't forget that you have recursion available in ANS Forth as well.
> Many of the "traditional" operations research procedures have
> natural recursive formulations.

Words to allow coding of recursion have been around for a very long
time -- they are not new to ANS-Forth. Aside from concern about
efficiency, the main barrier to effective use of recursion in Forth is
that most Forth systems have a very shallow return stack. ANS-Forth
does not prescribe a minimum depth for the return stack -- so
providing words to do recursion does not mean that recursive coding
will be feasible on all Standard systems.

On classic Forth systems the return stack was above the parameter
stack, so that the user could enlarge the return stack by resetting
the boundary. As far as I can tell, there is no such mechanism in
ANS-Forth. There is a way to query the environment to determine the
size of the return stack, but no way to set the return stack to a
required size.

Someone who plans to make systematic use of recursion in ANS-Forth
should check the size of the return stack first.


John J Wavrik
jjwa...@ucsd.edu Dept of Math 0112
Univ of Calif - San Diego
La Jolla, CA 92093-0112


W.Baden

unread,
Jul 19, 1996, 3:00:00 AM7/19/96
to

Jonah Thomas (JETh...@ix.netcom.com) wrote:

> If you want something to happen regardless you can put it after the final
> THEN but if you want it most times but not all, you have some thinking to do
> still. Is this really better than

> ... BEGIN ... 0= IF ... EXIT THEN ... 0= IF ... EXIT THEN ... 0= IF ... EXIT
> THEN AGAIN


I have found it exceptional to do the same thing after a successful
and unsuccessful search. Such an exception is a word JET calls
-LEADING.

: -LEADING ( c_addr u -- c_addr' u' )
BEGIN DUP
WHILE OVER C@ BL =
WHILE 1 /STRING
REPEAT THEN
;

So as a rule I prefer--

: foo
BEGIN ...
0= IF
cleanup
FALSE EXIT THEN
...
WHILE
...
REPEAT
cleanup'
TRUE
;

-- to two WHILEs.

An experiment I tried in the 80s used BUT.

: BUT 1 CS-ROLL ; IMMEDIATE

This is the only use I would approve of for CS-ROLL or CS-PICK.

: foo
BEGIN ...
IF BUT
...
WHILE
...
REPEAT
cleanup'
TRUE
ELSE
cleanup
FALSE
THEN
;

Of course TRUE and FALSE can be replaced by appropriate
actions for success and failure.

I keep BUT around to use in a first pass at untangling
spaghetti logic, and eliminate it as I go.
--
Procedamus in pace. Wil Baden Costa Mesa, California

john wavrik

unread,
Jul 19, 1996, 3:00:00 AM7/19/96
to


In article 24960 of comp.lang.forth Wil Baden meditates:

> Not everything in life is simple. So you apply
> structure --natural or artificial-- to give you
> a better overview. (One name for a particular
> kind of structure is "religion". Religion is
> structured programming applied to life.)

I dunno, Wil. From what I have heard, the religious view
of life is not that simple. The religious view is that life
is a module that has one entry point and TWO possible exit
points -- the choice of which is a very complex function of
what goes on inside the module.

Life is more like being asked to write the program before
you know the algorithm.

Paul E. Bennett

unread,
Jul 19, 1996, 3:00:00 AM7/19/96
to

In article <31EA4...@austin.finnigan.com>
mck...@austin.finnigan.com "Andrew McKewan" writes:

> I agree that structured conditionals are easier to read than programming
> with gotos, there are times when a goto can make code more efficient and
> easier to read. Of course, we do not have gotos in standard Forth.

Isn't he forgetting the biggest GOTO of them all?. ABORT.

Apart from states that were not what one expected, "error conditions" if you
like, there is hardly a need to force an early exit with the right choice of
control structure and proper factoring. One of the problems I found in some
circumstances was the need to check the state and if not as required to abort
the routine and do a couple of other tidy up things on the way like turning off
the drive motor and/or displaying a message. A simple ABORT or ABORT" was not
good enough.

Now I had not thought about the naming of this one too hard and the name seemed
obvious at the time but better suggestions are welcome. The words appeared in
Forthwrite in August 1994. Each little looped function seemed to require some
form of error exit and the straight ABORT would have left the system wondering
what the safe thing to do was. As this was known at the time the decision to
ABORT was made then it seemed obvious to perform the clean-up required within
the exit condition. The code was for an 83 standard system.

: ABORT; (S flag ---)
[COMPILE] IF ; IMMEDIATE

: ;: (S i*w --- ) (R j*w --- )
COMPILE ABORT [COMPILE] THEN ; IMMEDIATE

<usage>

: FUNC
BEGIN
..........
WHILE
..........
<status flag check> ABORT;
<error mitigation action> <error message> ;:
,normal action>
REPEAT ;

So there we go, two exits and quite tidy, so who says there is not GOTO's.


--
Paul E. Bennett <p...@transcontech.co.uk>
Transport Control Technology Ltd.
Tel: +44 (0)117-9499861
Going Forth Safely

Bill Zimmerly

unread,
Jul 19, 1996, 3:00:00 AM7/19/96
to bi...@inlink.com

Gary I Ellis wrote:
>
> I was hoping to stay out of this one :-)
>
> However noone's mentioned what I consider one of the fundamentals of good
> design, namely that each module should have one (and only one) entry point and
> one (and only one) exit point.
>
> Therefore on the face of it requirement for multiple exit points in the *design*
> is a bad thing.
>
> However I have frequently found when implementing, that "while" loops used for
> list searches and the like are naturally terminated by one of two conditions,
> i.e. reaching the end of the list, or finding what you were looking for. In
> these sorts of cases, the judicious use of an exit can simplify an otherwise
> ugly/complex/bad piece of code.
>
> With that one exception, (and error handlers which are a special case anyway)
> I've yet to find the need to code more than one exit point. If I find myself in
> this position I have always been able to cure it with better factorisation or a
> rationalisation of the original design.
>
> Gary I Ellis - Control Systems S/W Engineer | Shirley, Southampton, England
> Business: g...@mpeltd.demon.co.uk | Phone/Fax +44 (1703) 332188
> Personal: ga...@tcp.co.uk |
> WWW: http://www.tcp.co.uk/~garye | Quote temporarily out to lunch

I've been reading this thread for some time and was wondering
why this wasn't mentioned before too, Gary. I'm not sure, but
I think I read once that the best way to look at multiple
exits is all jumping to the "one" exit point! To me, this is
fine so long as one places *GREAT* emphasis on factoring and
keeping definitions *VERY* small. i.e. if it's more than 1/2
page...it's *WAY* too large.

My $.03 (inflation <grin>),
- Bill
--
\\\|///
\\ ~ ~ //
(/ @ @ /)
--------------oOOo-(_)-oOOo---------------------------
William B. Zimmerly (Bill) -
Systems Research & Development Manager / Webmaster
General American Life Insurance Company, Inc.
Amateur Radio Call: KA0YKO
Email Address: bi...@inlink.com
Home Page Address: www.inlink.com/~billz
~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._.,-*~'`^`'~*-,._

Jonah Thomas

unread,
Jul 19, 1996, 3:00:00 AM7/19/96
to

In <31EF9C...@inlink.com> Bill Zimmerly <bi...@inlink.com> writes:
>Gary I Ellis wrote:

>> However noone's mentioned what I consider one of the fundamentals of good
>> design, namely that each module should have one (and only one) entry point
and
>> one (and only one) exit point.

>> However I have frequently found when implementing, that "while" loops used

for
>> list searches and the like are naturally terminated by one of two
conditions,
>> i.e. reaching the end of the list, or finding what you were looking for.
In
>> these sorts of cases, the judicious use of an exit can simplify an
otherwise
>> ugly/complex/bad piece of code.

A BEGIN with multiple WHILEs can do just that.

... BEGIN ... WHILE ... WHILE ... WHILE ... REPEAT ... ELSE ... THEN ELSE ...
THEN ;

Each of these does its own independent ending but they all go to the same ;
when they're done. Of course, you have to carefully match up the WHILEs and
the ELSEs. And you have to be careful at each step about ending conditions.


If you want something to happen regardless you can put it after the final
THEN but if you want it most times but not all, you have some thinking to do
still. Is this really better than

... BEGIN ... 0= IF ... EXIT THEN ... 0= IF ... EXIT THEN ... 0= IF ... EXIT
THEN AGAIN

??

If you want something to happen every time at the end, you can call this
routine only from a 2nd routine that does that afterward.

Dividing it into small routines has some tradeoffs. Each of them is simpler
and easier to understand. Each of them can be tested independently. You
might be able to put the control structure into a simple thing that's easy to
understand. But it's possible to bury the complexity inside of things which
are individually simple but hard to follow -- it could be hard to see the
complex forest for the simple trees. That's a good kind of tradeoff to have,
though. The advantages are all things you can use, and the disadvantages are
mostly in the potential to do it unskillfully.

>I've been reading this thread for some time and was wondering
>why this wasn't mentioned before too, Gary. I'm not sure, but
>I think I read once that the best way to look at multiple
>exits is all jumping to the "one" exit point! To me, this is
>fine so long as one places *GREAT* emphasis on factoring and
>keeping definitions *VERY* small. i.e. if it's more than 1/2
>page...it's *WAY* too large.

Yes. If you can turn the problem into a simple things connected simply, it
isn't as important to follow traditional design rules to the letter. And if
the complexity isn't handled well then you can follow the rules
letter-perfect and still have trouble.


Zsoter Andras

unread,
Jul 20, 1996, 3:00:00 AM7/20/96
to

john wavrik (ir...@sdcc3.ucsd.edu) wrote:


>In article 24960 of comp.lang.forth Wil Baden meditates:

> I dunno, Wil. From what I have heard, the religious view
>of life is not that simple. The religious view is that life
>is a module that has one entry point and TWO possible exit

^^^^^^^^
Excuse me!
You and up dead OR you end up dead, that makes TWO exit points?

>points -- the choice of which is a very complex function of
>what goes on inside the module.

Andras


Frank Sergeant

unread,
Jul 20, 1996, 3:00:00 AM7/20/96
to

In article <4sprol$8...@hkusuc.hku.hk>,
h929...@hkuxa.hku.hk (Zsoter Andras) wrote:

> john wavrik (ir...@sdcc3.ucsd.edu) wrote:
> > I dunno, Wil. From what I have heard, the religious view
> >of life is not that simple. The religious view is that life
> >is a module that has one entry point and TWO possible exit
> ^^^^^^^^
> Excuse me!
> You and up dead OR you end up dead, that makes TWO exit points?

Andras, the reference was to a common Christian religion
belief that upon death a person's "soul" will go to either
Heaven or to Hell. This Christian religion background permeates
the "Western" culture, even among people who do not profess to
profess the Christian faith. It reminds me of the old joke:

You only have two things to worry about: either you'll stay
healthy or you'll get sick. If you stay healthy, there is nothing
to worry about.

If you get sick, you only have two things to worry about: either
you'll get well or you'll die. If you get well, there is nothing
to worry about.

If you die, you only have two things to worry about: either
you'll go to Heaven or to Hell. If you go to Heaven, there is
nothing to worry about.

If you go to Hell, you will be so busy shaking hands with
all your friends that you won't have time to worry.


-- Frank
py...@pobox.com (permanent)
http://www.eskimo.com/~pygmy


Richard Astle

unread,
Jul 21, 1996, 3:00:00 AM7/21/96
to

W.Baden wrote:
>
> In the thread 0123 Forth I posted a definition with _seven_
> exits. There are seven because there are seven places to
> terminate. The logic is simple, with no nested IFs or multiple
> WHILEs.
>
> It's fairly easy to reformulate this with just one exit.
> Of course, IFs are deeply nested.
>
> It's a matter of taste, but I find the version with multiple
> exits much easier to follow.
>
> I'm interested in seeing how a Strictly Structured disciple
> would do this definition.

> --
> Procedamus in pace. Wil Baden Costa Mesa, California

I think I will not be contradicted if I point out that the point of the "only one entry
point and exit per routine" dictum is to reduce the possibility of programmer confusion.
It's clear, I think, that in a definition spanning many screens (for those of us who
still use screens) indiscriminate EXITs along the way might cause such confusion. The
Pascal and/or C examples I think I remember seeing involve the possibility that the
programmer might return to update the routine (function, procedure) by placing
additional cleanup code just before its lexical end. However, Forth words are supposed
to be short anyway (we don't suffer as severe penalties for factoring as other languages
do), and when multiple EXITs make them even shorter (as they do in Wil's example and in
most of mine), then they REDUCE the possibility of confusion, and meet the GOAL of the
"only one entry point and exit per routine" dictum better than the dictum itself.

--Richard

W.Baden

unread,
Jul 21, 1996, 3:00:00 AM7/21/96
to

Zsoter Andras

unread,
Jul 22, 1996, 3:00:00 AM7/22/96
to

Frank Sergeant (py...@eskimo.com) wrote:
>In article <4sprol$8...@hkusuc.hku.hk>,
>h929...@hkuxa.hku.hk (Zsoter Andras) wrote:
>> john wavrik (ir...@sdcc3.ucsd.edu) wrote:
>> > I dunno, Wil. From what I have heard, the religious view
>> >of life is not that simple. The religious view is that life
>> >is a module that has one entry point and TWO possible exit
>> ^^^^^^^^
>> Excuse me!
>> You and up dead OR you end up dead, that makes TWO exit points?

> Andras, the reference was to a common Christian religion
>belief that upon death a person's "soul" will go to either
>Heaven or to Hell. This Christian religion background permeates
>the "Western" culture, even among people who do not profess to
>profess the Christian faith. It reminds me of the old joke:


Well, but where are the two EXIT points?

If you believe you don't die just leave Earth than there is no exit
at all just a change of states.
On the other hand if you believe that you die but your soul has an
afterlife that is another function call,
so
LIFE ( -- flag )
The effect of your life.
And the code is:
LIFE IF HEAVEN ELSE HELL ENDIF

I still don't see the two EXITs.

Andras


Bill Zimmerly

unread,
Jul 22, 1996, 3:00:00 AM7/22/96
to bi...@inlink.com

Zsoter Andras wrote:
>
> john wavrik (ir...@sdcc3.ucsd.edu) wrote:
>
> >In article 24960 of comp.lang.forth Wil Baden meditates:
>
> > I dunno, Wil. From what I have heard, the religious view
> >of life is not that simple. The religious view is that life
> >is a module that has one entry point and TWO possible exit
> ^^^^^^^^
> Excuse me!
> You and up dead OR you end up dead, that makes TWO exit points?
>
> >points -- the choice of which is a very complex function of
> >what goes on inside the module.
>
> Andras

Pardon me, Andras, but...lighten up dude! <grin> After all,
good Forth code doesn't know what code was calling it nor
what code will execute after it has made it's mark on the
state of the machine! (We may be locked in a BEGIN...UNTIL
loop, 'ya know. <big grin>)

Respectfully yours,

zn...@teleport.com

unread,
Jul 22, 1996, 3:00:00 AM7/22/96
to

john wavrik (ir...@sdcc3.ucsd.edu) wrote:

: On classic Forth systems the return stack was above the parameter

: stack, so that the user could enlarge the return stack by resetting
: the boundary. As far as I can tell, there is no such mechanism in
: ANS-Forth. There is a way to query the environment to determine the
: size of the return stack, but no way to set the return stack to a
: required size.

: Someone who plans to make systematic use of recursion in ANS-Forth
: should check the size of the return stack first.

Most of the ANS or near-ANS implementations I have played with allow
one, possibly by reassembling the kernel, to make the return stack
bigger. On the 8086 and its ilk, of course, there is the 64 KByte
segment limit to worry about, but if you have more than 64K bytes of
*anything* you have to make a special effort to manage things.

As Julian Noble pointed out the last time we had this discussion, it is
often possible to create an *efficient* recursive solution to a problem
which does not place large demands on either stack capacity or
subroutine call overhead. The best guide to such matters I've seen is
in the user manual for the Derive mathematics package; there is a whole
chapter on programming efficient recursive functions.

This is a good point, though. The ANS standard provides for an
optional memory allocation/deallocation wordset; maybe a stack size
increase/decrease wordset should also be made available.

--
zn...@teleport.com (M. Edward Borasky) http://www.teleport.com/~znmeb

"Outside of a dog, a book is a man's best friend. Inside a dog, it's
too dark to read." -- Marx

Elizabeth Rather

unread,
Jul 22, 1996, 3:00:00 AM7/22/96
to

john wavrik wrote:
> I dunno, Wil. From what I have heard, the religious view
> of life is not that simple. The religious view is that life
> is a module that has one entry point and TWO possible exit
> points -- the choice of which is a very complex function of
> what goes on inside the module.
I think there's only one exit point, but the module can affect the
return address.

> Life is more like being asked to write the program before
> you know the algorithm.

I believe the function of religion is to offer an algorithm.

Bill Zimmerly

unread,
Jul 22, 1996, 3:00:00 AM7/22/96
to bi...@inlink.com

W.Baden wrote:
>
> KNOWING WHERE YOU ARE.
>
> This is what Structured Programming does for you.

Excellently expressed and very succinct, I might add!

> Take any line: you know how you get there;
> you know where you're going next.
>
> GOTO can make this difficult. So can CATCH-THROW.

Without BRANCH and ?BRANCH, Forth would be difficult to
properly impliment. I'm glad the name was changed (to protect
the innocent??? <grin>)

> Add to this the limit of human comprehension,
> "the magical number 7, plus or minus 2", and
> you get the Prime Directive for programming and
> everything else. Not the gratuitous and insulting
> "Keep it simple, stupid", but Occam's Razor,
> "Keep it Short and Simple."
>
> (I think that 7 is too much. I believe that the
> highest number that any normal person knows is 5.
> After that, you have to partition. 6 is 2 3s or 3
> 2s or 4 and 2, or once in a rare while, 5 and 1.)


>
> Not everything in life is simple. So you apply
> structure --natural or artificial-- to give you
> a better overview. (One name for a particular
> kind of structure is "religion". Religion is
> structured programming applied to life.)

Now *that's* a novel way of looking at life! <grin>

> Every EXIT must be judged on its own merit. Some
> are virtuous, some are evil.

You must be part philosopher too, Will! For my own part I've
always believed that there was more to John 1:1 than most
realized, "...and the WORD was God...". <big grin>

Zsoter Andras

unread,
Jul 22, 1996, 3:00:00 AM7/22/96
to

Bill Zimmerly (bi...@inlink.com) wrote:

>Pardon me, Andras, but...lighten up dude! <grin> After all,
>good Forth code doesn't know what code was calling it nor
>what code will execute after it has made it's mark on the
>state of the machine! (We may be locked in a BEGIN...UNTIL
>loop, 'ya know. <big grin>)

If there is reincarnation we can be be locked up in an endless loop.
But it still does not make two entry points. ;-)

Andras


zn...@teleport.com

unread,
Jul 22, 1996, 3:00:00 AM7/22/96
to

Frank Sergeant (py...@eskimo.com) wrote:
: Andras, the reference was to a common Christian religion

: belief that upon death a person's "soul" will go to either
: Heaven or to Hell. This Christian religion background permeates
: the "Western" culture, even among people who do not profess to
: profess the Christian faith. It reminds me of the old joke:

: You only have two things to worry about: either you'll stay


: healthy or you'll get sick. If you stay healthy, there is nothing
: to worry about.

: If you get sick, you only have two things to worry about: either
: you'll get well or you'll die. If you get well, there is nothing
: to worry about.

: If you die, you only have two things to worry about: either
: you'll go to Heaven or to Hell. If you go to Heaven, there is
: nothing to worry about.

: If you go to Hell, you will be so busy shaking hands with
: all your friends that you won't have time to worry.

Speaking of nested conditionals, there was once a man who fell out of an
airplane. Fortunately, he was wearing a parachute. Unfortunately, the
parachute failed to open. Fortunately, there was a haystack directly
beneath him. Unfortunately, there was a pitchfork in the haystack.
Fortunately, he missed the pitchfork. Unfortunately, he also missed the
haystack.

How to Stop A Folksinger Cold # 1
"Home, home on the range, where the deer and the antelope play..."
The antelope cheats.

Bruce R. McFarling

unread,
Jul 23, 1996, 3:00:00 AM7/23/96
to

h929...@hkuxa.hku.hk (Zsoter Andras) wrote:

>Well, but where are the two EXIT points?

>If you believe you don't die just leave Earth than there is no exit
>at all just a change of states.

>On the other hand if you believe that you die but your soul has an
>afterlife that is another function call,
>so
>LIFE ( -- flag )
>The effect of your life.
>And the code is:
>LIFE IF HEAVEN ELSE HELL ENDIF

>I still don't see the two EXITs.

As an inheritence from Judaism, you can get to the afterlife by
dying (the normal exit, equivalent to a ';') or you can get there
straight: walking straight to heaven from the top of Mt. Sinai, or going
straight to heaven as part of the Second Coming process (which would be
the special case 'EXIT' in the analogy).

Of course, in considering the ';' the normal exit, then the
subject header 'Is using multiple Exits bad programming' is ambiguous:
is it using multiple exits, or using multiple EXITs? Read the second
way, setting up a loop to exit success or failure as the normal case,
and using an explicit EXIT for the alternate case, is two exits but
only one EXIT.

And using 7 exits to simplify the code is an example of the
silver rule: don't let good rules interfere with good solutions.

--
Virtually,

Bruce R. McFarling, Newcastle, NSW
ec...@cc.newcastle.edu.au

Zsoter Andras

unread,
Jul 23, 1996, 3:00:00 AM7/23/96
to

Bruce R. McFarling (ec...@cc.newcastle.edu.au) wrote:

> And using 7 exits to simplify the code is an example of the
>silver rule: don't let good rules interfere with good solutions.

I like this.

In the sources of DOOF (in C++) there is a function with somewhere in
between fifty to a hundred return statements in it.
Any other solution would have been clumsy, but I am always afraid that
somebody will roast me on slow fire because "A function should have
exactly one return.". ;-)

Andras


Julian V. Noble

unread,
Jul 23, 1996, 3:00:00 AM7/23/96
to

I could not agree more re: using a state machine generator. I have
given an ANS compatible version of my FSM mini-compiler in an article that
was supposed to have appeared in JFAR 2 years ago (actually, an earlier
version was to have appeared _6_ years ago!). If there is general inter-
est I will post the code at taygeta, together with the article.

Several commercial applications have been written using my method,
so it is a pity it is not more widely known. The code is really quite
short, and compiles a state transition table into an FSM. It is
also easy, using this method, to do nondeterministic FSMs as well
as deterministic automata.


--
Julian V. Noble
j...@virginia.edu

Julian V. Noble

unread,
Jul 23, 1996, 3:00:00 AM7/23/96
to

wilb...@netcom.com writes:
> KNOWING WHERE YOU ARE.
>
> This is what Structured Programming does for you.

[ deletions ]



> Not everything in life is simple. So you apply
> structure --natural or artificial-- to give you
> a better overview. (One name for a particular
> kind of structure is "religion". Religion is
> structured programming applied to life.)
>

> Every EXIT must be judged on its own merit. Some
> are virtuous, some are evil.

Are you speaking ex cathedra, and saying "not everyone
makes a good EXIT" ? If so, I agree. :-)

W.Baden

unread,
Jul 23, 1996, 3:00:00 AM7/23/96
to

COMMENT

The definition of PRIME given in 0123 Forth has a lot
of duplicated code. It would be nice to factor it out.

Besides adding execution overhead we don't want, we
couldn't exit properly.

Macros give a solution.

(Flames awaited.)

[THEN]

: ?? PARSE-WORD >PAD PLEASE " IF ~ THEN " ; IMMEDIATE

: DIVISIBLE-BY PARSE-WORD >PAD 2DUP PLEASE
" DUP ~ MOD 0= IF ~ = EXIT THEN "
; IMMEDIATE

: SUCCESS PLEASE " 2DROP TRUE EXIT " ; IMMEDIATE

: FAILURE PLEASE " 2DROP FALSE EXIT " ; IMMEDIATE

: PRIME ( N -- flag )
DIVISIBLE-BY 2
DIVISIBLE-BY 3
DIVISIBLE-BY 5
5 ( N divisor)
BEGIN
2 +
2DUP DUP * U< ?? SUCCESS
2DUP MOD 0= ?? FAILURE
4 +
2DUP DUP * U< ?? SUCCESS
2DUP MOD 0=
UNTIL
FAILURE ( flag)
;

Tom Zimmer

unread,
Jul 23, 1996, 3:00:00 AM7/23/96
to

I will certainly not be critical of anyone using multiple exits, since
I use them myself often enough. It would be interesting though to
perhaps go through the mental exercise of trying to figure out if there
are any other (good) solutions to a particular multiple exit problem.
I can't think of any example problems at the moment, does anyone else
have a problem thats looking (not looking) for a solution?

I also confess that I haven't been reading this thread closely, so if
you have already done this, just ignore my suggestion.

Tom Zimmer

Brad Eckert

unread,
Jul 23, 1996, 3:00:00 AM7/23/96
to

be...@paysan.modem.informatik.tu-muenchen.de (Bernd Paysan) wrote:
[snip]

>Complicated state machines should be handled with a state machine
>generator, thus a dispatch routine that goes through a table. As Forth
>is a very extensible language, it is not too hard (compared with the
>rest of the problem) to build such a state machine generator. I saw
>something like this in ComForth for Windows, which has "WHEN"-Lists
>for event processing. In fact, a state-machine generator could use
>such "WHEN"-lists to generate the state machine. E.g. you say
>
>:noname keep-card ." Your card is kept because " .reason cr
> ." Please contact your credit institute" cr terminate ;
> 3-times-pid-wrong WHEN card-is-locked OR-WHEN
>
>:noname start-transaktion;
> pid-ok WHEN
>
>:noname output-money ;
> transaktion-ok WHEN
>--
>Bernd Paysan
>"Late answers are wrong answers!"
>http://www.informatik.tu-muenchen.de/~paysan/

Well, that's a really cool idea. I envision WHEN as being a defining
word that would BL WORD its argument from the input stream. Is a state
machine lexicon available on taygeta? Otherwise, what other words would
be useful? I suppose :STATEMACHINE <name> and ;STATEMACHINE could begin
and end the tables, and <name> would go through the table until it finds
a true condition or hits the end of the table. Or am I way off?

-- Brad


Elizabeth Rather

unread,
Jul 23, 1996, 3:00:00 AM7/23/96
to

Zsoter Andras wrote:
>...

> In the sources of DOOF (in C++) there is a function with somewhere in
> between fifty to a hundred return statements in it.
> Any other solution would have been clumsy, but I am always afraid that
> somebody will roast me on slow fire because "A function should have
> exactly one return.". ;-)

I'd sure blanch at having to maintain a single function with so many
returns. Surely another approach, such as an execution vector, would
handle such a situation more straightforwardly.

Bruce R. McFarling

unread,
Jul 24, 1996, 3:00:00 AM7/24/96
to j...@faraday.clas.virginia.edu

j...@faraday.clas.Virginia.EDU (Julian V. Noble) wrote:

>I could not agree more re: using a state machine generator.


>I have given an ANS compatible version of my FSM mini-compiler
>in an article that was supposed to have appeared in JFAR 2
>years ago (actually, an earlier version was to have appeared

>_6_ years ago!). If there is general interest I will post the


>code at taygeta, together with the article.

Consider this one expression of interest. I hope you get
enough to support a generalization.

David N. Williams

unread,
Jul 24, 1996, 3:00:00 AM7/24/96
to
Bruce R. McFarling wrote: > j...@faraday.clas.Virginia.EDU (Julian V. Noble) wrote: > >I could not agree more re: using a state machine generator. > >I have given an ANS compatible version of my FSM mini-compiler > >in an article that was supposed to have appeared in JFAR 2 > >years ago (actually, an earlier version was to have appeared > >_6_ years ago!). If there is general interest I will post the > >code at taygeta, together with the article. > Consider this one expression of interest. I hope you get > enough to support a generalization. Here's another! --David _ _________________________________________________________________ (_\(__ _|__) David N. Williams Phone: 1-(313)-764-5236 __|___ University of Michigan Fax: 1-(313)-763-2213 \ |:-) Physics Department Email: David.N....@umich.edu \| Ann Arbor, MI 48109-1120

David N. Williams

unread,
Jul 24, 1996, 3:00:00 AM7/24/96
to

W.Baden wrote:
>
> COMMENT
>
> The definition of PRIME given in 0123 Forth has a lot
> of duplicated code. It would be nice to factor it out.
>
> Besides adding execution overhead we don't want, we
> couldn't exit properly.
>
> Macros give a solution.
>
> (Flames awaited.)

No flames from me! I appreciate the power of macros in Forth, and use
them extensively. Someday RSN I hope to sit down with PLEASE and see
what I can learn from it.

Bill Zimmerly

unread,
Jul 24, 1996, 3:00:00 AM7/24/96
to

Touche! <grin>

Perhaps we can influence the variables and values of "THE BIG MACHINE" so that our next incarnation
is a little less stressful, eh?

- Bill

P.S. BTW, Great job on the DOS-Extended version you wrote (I forgot the name of the system, but
not your name). I was evaluating it for a project early last year, but it was rejected for one
reason alone...DOS! :-(

Michael A. Losh

unread,
Jul 24, 1996, 3:00:00 AM7/24/96
to

Tom Zimmer wrote:
> I will certainly not be critical of anyone using multiple exits, since
> I use them myself often enough.

I appologize if I'm unknowingly repeating someone else's comments, but
IMHO, the kind of multiple exit being discussed here is a different, and
much less heinous beast than the one banished by "A function should have
exactly one return."

It is my understanding that structured programming, as promoted by
Dijkstra, simply requires that software be broken into _modules_ that
have one entry point and one exit point. Such a module will guarantee
that the thread of execution, as it leaves a module, will go to one and
only one place.

Forth's words, no matter how many EXITs they have inside, have one entry
point and one exit point*. The EXITs force the code to the common
return point. This is still structured, or nearly so. The same idea
applies to multiple "return();" statements in C.

( * Of course, the ABORT statement, and other exception-handling
mechanisms, in whatever language, bend this rule. But this is one area
that nearly all experts agree that it is acceptable to use a GOTO or
another type of "unstructured" change in the control flow.)

The really awful type of multiple exit is where a routine may exit at
differet points inside the function in order to continue in _different_
directions, perhaps in different routines. This is the classic
"spaghetti code" caused by improper use of the GOTO statement, and is
the target of the "one return" rule.

So I would say, don't fret over a few extra EXITs or returns, especially
if they prevent a deeply nested mess inside a routine. Just do not
abuse them. The people who get all caught up in a rule like "one
return" do not seem to understand its purpose very well. That's
probably true of most things in life!
--
Mike Losh ml...@tir.com

Michael Kalus

unread,
Jul 24, 1996, 3:00:00 AM7/24/96
to

Hi ec...@cc.newcastle.edu.au
or others

> >... using a state machine generator.

What is a state machine?
Can you give a simple Forth example?

I can use ANS and understand most of the discussion here in c.l.f

Yours sincerely. MK
Grüße aus Bad Malente, Michael
## CrossPoint v3.02 ##

W.Baden

unread,
Jul 25, 1996, 3:00:00 AM7/25/96
to

Michael Kalus (mic...@malente.forth-ev.de) wrote:

> What is a state machine?

Chuck Moore has told me that he invented Forth as a replacement
for finite state machines, which were in vogue 30 years ago.

A finite state machine is a compound CASE statement within
a BEGIN-loop.

HTH.


Tom Zimmer

unread,
Jul 25, 1996, 3:00:00 AM7/25/96
to

Michael A. Losh wrote:
>
> Tom Zimmer wrote:
> > I will certainly not be critical of anyone using multiple exits, since
> > I use them myself often enough.

<Good Stuff, but snipped>

> So I would say, don't fret over a few extra EXITs or returns, especially
> if they prevent a deeply nested mess inside a routine. Just do not
> abuse them. The people who get all caught up in a rule like "one
> return" do not seem to understand its purpose very well. That's
> probably true of most things in life!

Thank you Michael for that clear definition.

So it seems to me that the type of exit you don't want would be something
like this;

: do-char ( c1 -- c1 | )
dup bl [char] ~ between
if emit
R> DROP EXIT
then ;

: do-ctrl ( c1 -- c1 | )
dup bl <
if drop
R> DROP EXIT
then ;

: do-keys ( c1 -- )
do-char
do-ctrl
.. do with whatever is left....
;

So that "do with whatever is left" is only executed if c1 is not a displayable
(english) character, or a control character.

I have used this before, and it works well, but it is dangerous, since
any word using either do-char or do-ctrl must know that they may not return,
and they must not put anything on the return stack, which would then cause
a crash that would be hard to find.

Tom Zimmer

zn...@teleport.com

unread,
Jul 25, 1996, 3:00:00 AM7/25/96
to

W.Baden (wilb...@netcom.com) wrote:
: Michael Kalus (mic...@malente.forth-ev.de) wrote:

: HTH.

It looks like it's time for me to jump in here and throw a few more
irons into this fire:

1. Back when Julian Noble and I were young sprouts practicing the craft
of scientific programming (Fortran II, three-branch IFs only :-),
our business-programming brethren were happily structuring their
software with something called decision tables. So while we were
slaving away writing spaghetti code, which is all you can do with a
three-branch IF and a DO-loop, the COBOL guys had this all figured
out.

2. I rather like the Edsger Dijkstra guarded command syntax as developed
in "A Discipline of Programming". Now *there's* a book that's crying
out to be translated into Forth! I'm sure by now someone has
translated his *two* control structures into Forth -- I didn't see it
in my indexes of Forth Dimensions or FORML proceedings, though. If
no one has done it, I might be persuaded to use the ANS
"roll-your-own-control-structure" words (CS-ROLL, CS-PICK, AHEAD) to
do a sequentrial implementation without Dijkstra's non-deterministic
semantics.

3. The one-entry/one-exit rule is basically a good one; it enhances
readability. Decision tables, Warnier-Orr diagrams and other such
ways of simplifying the program flow graph are also good ideas. Such
rigid structures make it very easy for an optimizing compiler to do
high-powered control and data flow analysis (another thing that is
crying out to be done in Forth)!

4. The mantra of replacing branches with computed formulas is another
good idea; like most such ideas, it did not originate with Forth :-).
One does, however, need to constantly evaluate the tradeoffs between
computing time and memory space; in embedded systems we often have
small amounts of both to work with.

How to Stop A Folksinger Cold # 2
"Are you going to Scarborough Fair?..."
No.

Zsoter Andras

unread,
Jul 26, 1996, 3:00:00 AM7/26/96
to

zn...@teleport.com wrote:

>1. Back when Julian Noble and I were young sprouts practicing the craft
> of scientific programming (Fortran II, three-branch IFs only :-),
> our business-programming brethren were happily structuring their
> software with something called decision tables. So while we were
> slaving away writing spaghetti code, which is all you can do with a
> three-branch IF and a DO-loop, the COBOL guys had this all figured
> out.

What is wrong with a three-branch-if?
I rather miss them in HLL-s (Assembly naturally works nearly that way).

Andras


Richard Astle

unread,
Jul 26, 1996, 3:00:00 AM7/26/96
to

Tom Zimmer wrote:
>
> Michael A. Losh wrote:
> >
> > Tom Zimmer wrote:
-- stuff deleted

I do this kind of think perhaps far too often, on a project that keeps growing in the
same amount of space. It's useful for factoring out a common error routine etc.
Anyway, whatever the usefulness, and whatever the recklessness, I make the construct a
little less dangerous by ending the name of all words that contain RDROP (I use it so
much I've coded R> DROP this way) with the | character, to let me know the word with
that name might hit a wall, exiting the word that calls it.

: DO-KEYS ( c1 -- )
DO-CHAR|
DO-CTRL|

.. do with whatever is left....
;

Fortunately I had no other naming convention that involved the | character. Of course
you could also make DO-CHAR etc. return a flag, and do

: do-keys ( c1 -- )

do-char? 0= if exit then
do-ctrl? 0= if exit then


.. do with whatever is left....
;

but who would want to?

By the way, when did it become fashionable to make Forths case insensitive?

-- Richard

zn...@teleport.com

unread,
Jul 26, 1996, 3:00:00 AM7/26/96
to

Zsoter Andras (h929...@hkuxa.hku.hk) wrote:
: zn...@teleport.com wrote:

The only reason the three-branch IF was created is that the original
target machine for FORTRAN, the IBM 704, had a compare instruction that
branched three ways depending on a value being 0= 0< or 0> (sneaky -- I
specified it in Forth :-).

I support the right to keep and arm bears.

Mike Coughlin

unread,
Jul 26, 1996, 3:00:00 AM7/26/96
to

In article <4t9qre$a...@hkusuc.hku.hk>,

Zsoter Andras <h929...@hkuxa.hku.hk> wrote:
>zn...@teleport.com wrote:

>>1. Back when Julian Noble and I were young sprouts practicing the craft
>> of scientific programming (Fortran II, three-branch IFs only :-),
>> our business-programming brethren were happily structuring their
>> software with something called decision tables. So while we were
>> slaving away writing spaghetti code, which is all you can do with a
>> three-branch IF and a DO-loop, the COBOL guys had this all figured
>> out.

>What is wrong with a three-branch-if?
>I rather miss them in HLL-s (Assembly naturally works nearly that way).

The three branch if caused the most number of coding errors
in the old days when I had to use it. The other big error generator
was Fortran's automatic creation of new variables when I defined
a variable by mistake and didn't set its value. As time went on,
I got better at finding mistakes in variables, but I still had
just as many problems with the three valued if statement.

Assembly language programming is much more difficult than
necessary since it uses so many things that the human mind
cannot cope with. A good language like Forth removes sources
of error by removing the methods that cause errors.


--
Michael Coughlin mi...@gnu.ai.mit.edu Cambridge, MA USA

Tom Zimmer

unread,
Jul 26, 1996, 3:00:00 AM7/26/96
to

Richard Astle wrote:
>
> By the way, when did it become fashionable to make Forths case insensitive?
>

It has always been popular with me. I can never remember what the right
case for a word is. I do however often use mixed case when I enter words
for readability, but not findability.

Tom Zimmer

Julian V. Noble

unread,
Jul 26, 1996, 3:00:00 AM7/26/96
to

zn...@teleport.com writes:

[ previous deleted ]

> It looks like it's time for me to jump in here and throw a few more
> irons into this fire:
>

> 1. Back when Julian Noble and I were young sprouts practicing the craft
> of scientific programming (Fortran II, three-branch IFs only :-),
> our business-programming brethren were happily structuring their
> software with something called decision tables. So while we were
> slaving away writing spaghetti code, which is all you can do with a
> three-branch IF and a DO-loop, the COBOL guys had this all figured
> out.

[ point # 2 on deleted ]

Noble's response to Point #1 above:

Sorry to differ. But FORTRAN II contained both assigned and computed
GOTO's, which are perfectly adequate to implement a decision table:

SUBROUTINE FSM(ICOL)
COMMON ISTATE
C
C THIS IS A STATE MACHINE, A SPECIAL CASE OF A DECISION TABLE
C USING COMPUTED GOTO.
C
C THE STATE VARIABLE IS KEPT IN COMMON STORAGE
C
GOTO (1,2,3,4,5,6), ICOL+ISTATE+ISTATE
C
C THERE ARE 2 STATES, ISTATE=0 OR 1
C AND 3 COLUMNS, ICOL=1,2,3 IN THE STATE TABLE
C
1 CALL ACTION1
ISTATE = ?
RETURN
2 CALL ACTION2
ISTATE = ?
RETURN
C
C ETC.
C
6 CALL ACTION6
ISTATE = ?
RETURN
END

Note that BASIC has a similar construct,

ON expression GOTO linelist

The real virtue of Forth (and my approach therein) becomes apparent when one
wishes to construct more than one decision table or state machine. The other
virtue is plain readability, since a state machine constructed by compiling
its tabular representation is self-documenting.

Finally I should note that Glen Haydon says my FSM paper is going to appear
in the electronic version of JFAR, which will appear at a URL that I have
been sworn not to reveal yet. (I know nothing whatsoever about the electronic
version of JFAR, which is a bit surprising since I could have sworn that I
have been a member of its editorial board since 1992 or 1993. But that's
how these things go sometimes...)

Wolfgang Allinger

unread,
Jul 26, 1996, 3:00:00 AM7/26/96
to

On 24 Jul 96 in article <31F6EF...@tir.com>

<ml...@tir.com> (Michael A. Losh) wrote:

>It is my understanding that structured programming, as promoted by
>Dijkstra, simply requires that software be broken into _modules_
>that have one entry point and one exit point. Such a module will
>guarantee that the thread of execution, as it leaves a module, will
>go to one and only one place.

---snipp---


>Forth's words, no matter how many EXITs they have inside, have one
>entry point and one exit point*. The EXITs force the code to the
>common return point. This is still structured, or nearly so. The
>same idea applies to multiple "return();" statements in C.

---snipp---


>So I would say, don't fret over a few extra EXITs or returns,
>especially if they prevent a deeply nested mess inside a routine.
>Just do not abuse them. The people who get all caught up in a rule
>like "one return" do not seem to understand its purpose very well.
>That's probably true of most things in life!

>--
>Mike Losh ml...@tir.com

Hi Mike,

I think, that I understand the purpose of 'one return' very well:

I'm not quite shure if Dijkstra also made his statement by thinking on
InCircuitEmulation and/or debugging of (machine)code.

It is very useful to have only one RETurn statement in a routine.
Especially if you have not very much number of possible breakpoints. It's
also good practice, If you want to trace programms with a logic analyser.
Sometimes I like two RETurns in my (low-level)programs: one for normal
exit, the other one for error exit.

In forth words I use a lot of 'IF ... EXIT THEN' in the beginning to
handle the special cases. A logic analyser is nearly useless in forth, so
I do what it makes it easier for me.

Bye bye by Wolfgang

--
FORTHing @ work Cheap
Fast Good ...pick any two of them
Dipl.-Ing. Wolfgang Allinger
Brander Weg 6 Voice/FAX [+49] [0] 212 / 66 8 11
D-42699 SOLINGEN eMail: a...@business.forth-ev.de
GERMANY
## CrossPoint v3.1 R ##

Wolfgang Allinger

unread,
Jul 26, 1996, 3:00:00 AM7/26/96
to

On 24 Jul 96 in article <4t5plk$f...@hkusuc.hku.hk>
<h929...@hkuxa.hku.hk> (Zsoter Andras) wrote:

--- snipp ---

>BTW: Another use of multimple exits is my favorite construct (good
>for factoring into very small, and readable words) is:
>
> Blah, blah IF <something> EXIT ENDIF
> The rest of the word
>
>Instead of the IF ELSE or <The rest of the word nested
>between IF and EENDIF.
>
>I don't know why, but I like it, even though I use it more often
>when programming in Pascal or C than in Forth.
>
>Andras

Hallo Andras,

I like that too! I do it since many years now and I'm still happy. I think
Leo Brodie mentioned this style in one of his excellent books.

Zsoter Andras

unread,
Jul 27, 1996, 3:00:00 AM7/27/96
to

Mike Coughlin (mi...@gnu.ai.mit.edu) wrote:

> Assembly language programming is much more difficult than
>necessary since it uses so many things that the human mind
>cannot cope with. A good language like Forth removes sources
>of error by removing the methods that cause errors.

A gun which refuses to assist you to shoot yourself on the foot? ;-)

Andras


Zsoter Andras

unread,
Jul 27, 1996, 3:00:00 AM7/27/96
to

The same with me.
Mixed case spelling makes sources a lot more readable:

DeleteArray instead of DELETEARRAY , deletearray or delete_array (the latter
one is C-ish).

On the other hand when I communicate with my Forth interactively
I don't want it to refuse if I type in something spelled in the wrong
case (would be very inconvenient when I do something in a hurry)
so I prefer case-insetive Forth.

Andras


Paul Shirley

unread,
Jul 28, 1996, 3:00:00 AM7/28/96
to

In article <4taiqb$h...@life.ai.mit.edu>, Mike Coughlin
<mi...@gnu.ai.mit.edu> writes

> Assembly language programming is much more difficult than
>necessary since it uses so many things that the human mind
>cannot cope with. A good language like Forth removes sources
>of error by removing the methods that cause errors.

This puzzles the hell out of me. What are these things asm has 'the
human mind cannot cope with', and why do I find asm easier than most
HLLs?

Good languages reduce errors by filling in the details, doing it
correctly every time. At least 50% of my asm errors are forgetting to
do something simple (like balance the stack ;) that a HLL would either
trap or do for me.

The abstractions away from the simple test&branch level of asm provides
useful protection from these sort of mistakes. It also allows you to use
potentially dangerous techniques with more chance of success. (like
exiting from the middle of code) Unfortunately Forth does not provide
quite the same level of assistance here (a consequence of extreme
flexibility).

--
Paul Shirley

zn...@teleport.com

unread,
Jul 29, 1996, 3:00:00 AM7/29/96
to

Julian V. Noble (j...@faraday.clas.Virginia.EDU) wrote:

: Finally I should note that Glen Haydon says my FSM paper is going to appear


: in the electronic version of JFAR, which will appear at a URL that I have
: been sworn not to reveal yet. (I know nothing whatsoever about the electronic
: version of JFAR, which is a bit surprising since I could have sworn that I
: have been a member of its editorial board since 1992 or 1993. But that's
: how these things go sometimes...)

Try

http://www.taygeta.com/jfar/article001.html

"Outside of a dog, a book is a man's best friend. Inside a dog, it's
too dark to read." -- Marx

zn...@teleport.com

unread,
Jul 29, 1996, 3:00:00 AM7/29/96
to

Wolfgang Allinger (A...@business.forth-ev.de) wrote:
: I think, that I understand the purpose of 'one return' very well:

: I'm not quite shure if Dijkstra also made his statement by thinking on
: InCircuitEmulation and/or debugging of (machine)code.

Dijkstra has been in the business since before there were ones and
zeroes :-). His principles are applicable to *all* kinds of
programming: scientific and commercial applications, embedded,
assembler, compilers, operating systems -- even Forth, as some code I'm
in the process of writing up for Forth Dimensions shows.

: It is very useful to have only one RETurn statement in a routine.

: Especially if you have not very much number of possible breakpoints. It's
: also good practice, If you want to trace programms with a logic analyser.
: Sometimes I like two RETurns in my (low-level)programs: one for normal
: exit, the other one for error exit.

: In forth words I use a lot of 'IF ... EXIT THEN' in the beginning to
: handle the special cases. A logic analyser is nearly useless in forth, so
: I do what it makes it easier for me.

Correct me if I'm wrong, but doesn't a logic analyzer operate by
sampling the busses and displaying instruction and data addresses? If
so, I'd think it would be possible to write your Forth code in a manner
that catered to this.

: --


: FORTHing @ work Cheap
: Fast Good ...pick any two of them

I'll take *real* cheap and *real* fast!

I support the right to keep and arm bears.

Anton Ertl

unread,
Jul 30, 1996, 3:00:00 AM7/30/96
to

In article <4so93r$d...@dfw-ixnews6.ix.netcom.com>, JETh...@ix.netcom.com (Jonah Thomas) writes:
|> ... BEGIN ... WHILE ... WHILE ... WHILE ... REPEAT ... ELSE ... THEN ELSE ...
|> THEN ;

While this is certainly useful, I find it hard to follow which ELSE or
THEN belongs to which WHILE. I'd rather write it like this:

BEGIN
... IF
... AHEAD [ 1 CS-ROLL ] THEN [ 1 CS-ROLL ]
... IF
... AHEAD [ 1 CS-ROLL ] THEN [ 1 CS-ROLL ]
... IF
... AHEAD [ 1 CS-ROLL ] THEN [ 1 CS-ROLL ]
...
AGAIN THEN THEN THEN

or so.

Of course, I would hide the low-level control-structure words behind
new high-level words, e.g.:

START
... IF
... LEAVE-LOOP
... IF
... LEAVE-LOOP
... IF
... LEAVE-LOOP
...
END

(yes, the names may not be optimal).

These words are defined like this:

variable count-leaves

: START ( -- n dest )
count-leaves @ 0 count-leaves ! POSTPONE begin ; immediate

: LEAVE-LOOP ( dest orig1 -- orig2 dest )
1 count-leaves +! POSTPONE ahead 1 cs-roll POSTPONE then 1 cs-roll ; immediate

: END ( n orig1 ... orign dest -- )
POSTPONE again
count-leaves @ 0 ?DO
POSTPONE then
LOOP
count-leaves ! ; immediate

- anton
--
M. Anton Ertl Some things have to be seen to be believed
an...@mips.complang.tuwien.ac.at Most things have to be believed to be seen
http://www.complang.tuwien.ac.at/anton/home.html

Andrew Haley

unread,
Jul 30, 1996, 3:00:00 AM7/30/96
to

zn...@teleport.com wrote:
: Wolfgang Allinger (A...@business.forth-ev.de) wrote:
: : In forth words I use a lot of 'IF ... EXIT THEN' in the beginning to
: : handle the special cases. A logic analyser is nearly useless in forth, so
: : I do what it makes it easier for me.

: Correct me if I'm wrong, but doesn't a logic analyzer operate by
: sampling the busses and displaying instruction and data addresses? If
: so, I'd think it would be possible to write your Forth code in a manner
: that catered to this.

That's not really the point. If you use Forth to develop embedded
applications, a logic analyzer is redundant: you use interactivity
instead of staring at traces. Interactivity is cheaper and more
productive.

Andrew.

zn...@teleport.com

unread,
Jul 30, 1996, 3:00:00 AM7/30/96
to

Anton Ertl (an...@a0.complang.tuwien.ac.at) wrote:
: Of course, I would hide the low-level control-structure words behind
: new high-level words, e.g.:

: START
: ... IF
: ... LEAVE-LOOP
: ... IF
: ... LEAVE-LOOP
: ... IF
: ... LEAVE-LOOP
: ...
: END

: These words are defined like this:

: variable count-leaves

: : START ( -- n dest )
: count-leaves @ 0 count-leaves ! POSTPONE begin ; immediate

: : LEAVE-LOOP ( dest orig1 -- orig2 dest )
: 1 count-leaves +! POSTPONE ahead 1 cs-roll POSTPONE then 1 cs-roll ; immediate

: : END ( n orig1 ... orign dest -- )
: POSTPONE again
: count-leaves @ 0 ?DO
: POSTPONE then
: LOOP
: count-leaves ! ; immediate

: - anton
: --
: M. Anton Ertl Some things have to be seen to be believed
: an...@mips.complang.tuwien.ac.at Most things have to be believed to be seen
: http://www.complang.tuwien.ac.at/anton/home.html

Have you been peeking inside my HP100LX Palmtop?? :-) I am currently
writing up a very similar solution to this problem for submission to
Forth Dimensions. With any luck at all, I'll have it done in a day or
two.

What is it about

@replace(@string(@log(10000)*@atan(1),9),0,0,@char(112)&@char(105)&@char(61))

that you don't understand?

Bill Zimmerly

unread,
Jul 30, 1996, 3:00:00 AM7/30/96
to bi...@inlink.com

zn...@teleport.com wrote:
> ...[snip]

> Correct me if I'm wrong, but doesn't a logic analyzer operate by
> sampling the busses and displaying instruction and data addresses? If
> so, I'd think it would be possible to write your Forth code in a manner
> that catered to this.

It's been over 12 years since I've done this kind of
programming, but yes, that's (was?) a good way to do it.

> I'll take *real* cheap and *real* fast!

<grin>

> I support the right to keep and arm bears.

Bears are already scary enough, but dislexics interpreting
the U.S. Constitution are even more scary.

- Bill

Bill Zimmerly

unread,
Jul 30, 1996, 3:00:00 AM7/30/96
to bi...@inlink.com

zn...@teleport.com wrote:
> ...[snip]
> ...

> 2. I rather like the Edsger Dijkstra guarded command syntax as developed
> in "A Discipline of Programming". Now *there's* a book that's crying
> out to be translated into Forth! I'm sure by now someone has
> translated his *two* control structures into Forth -- I didn't see it
> in my indexes of Forth Dimensions or FORML proceedings, though. If
> no one has done it, I might be persuaded to use the ANS
> "roll-your-own-control-structure" words (CS-ROLL, CS-PICK, AHEAD) to
> do a sequentrial implementation without Dijkstra's non-deterministic
> semantics.

Excellent suggestion!

Bill Zimmerly

unread,
Jul 30, 1996, 3:00:00 AM7/30/96
to bi...@inlink.com

Brad Eckert wrote:
>
> be...@paysan.modem.informatik.tu-muenchen.de (Bernd Paysan) wrote:
> [snip]
> >Complicated state machines should be handled with a state machine
> >generator, thus a dispatch routine that goes through a table. As Forth
> >is a very extensible language, it is not too hard (compared with the
> >rest of the problem) to build such a state machine generator. I saw
> >something like this in ComForth for Windows, which has "WHEN"-Lists
> >for event processing. In fact, a state-machine generator could use
> >such "WHEN"-lists to generate the state machine. E.g. you say
> >
> >:noname keep-card ." Your card is kept because " .reason cr
> > ." Please contact your credit institute" cr terminate ;
> > 3-times-pid-wrong WHEN card-is-locked OR-WHEN
> >
> >:noname start-transaktion;
> > pid-ok WHEN
> >
> >:noname output-money ;
> > transaktion-ok WHEN
> >--
> >Bernd Paysan
> >"Late answers are wrong answers!"
> >http://www.informatik.tu-muenchen.de/~paysan/
>
> Well, that's a really cool idea. I envision WHEN as being a defining
> word that would BL WORD its argument from the input stream. Is a state
> machine lexicon available on taygeta? Otherwise, what other words would
> be useful? I suppose :STATEMACHINE <name> and ;STATEMACHINE could begin
> and end the tables, and <name> would go through the table until it finds
> a true condition or hits the end of the table. Or am I way off?
>
> -- Brad

I agree with Brad, that *is* a cool idea...it's too good an
idea to not impliment under Win32For...I think I'll work on
it and get back in a few weeks...

Ewald Pfau

unread,
Jul 31, 1996, 3:00:00 AM7/31/96
to

(Jet Thomas:)

|> ... BEGIN ... WHILE ... WHILE ... WHILE ... REPEAT ... ELSE ... THEN ELSE
...
|> THEN ;

(Anton Ertl:)
AE> BEGIN
AE> ... IF
AE> ... AHEAD [ 1 CS-ROLL ] THEN [ 1 CS-ROLL ]
AE> ... IF
AE> ... AHEAD [ 1 CS-ROLL ] THEN [ 1 CS-ROLL ]
AE> ... IF
AE> ... AHEAD [ 1 CS-ROLL ] THEN [ 1 CS-ROLL ]
AE> ...
AE> AGAIN THEN THEN THEN

There seems to be a specific dialect for indenting:

(stuff... flag) IF
(stuff... flag) IF
THEN
. THEN

Pairs are not that easily being parsed this way. Replace the above with:

(stuff... flag)
IF (stuff... flag)
. IF
. THEN
THEN

After this, indenting comes with loops.

BEGIN (stuff.. flag)
WHILE (stuff.. flag)
UNTIL
THEN

By this, the CS-ROLL (in WHILE) is hidden, so two jumps have to be comprehended
at one sight.

It would be:

BEGIN
. WHILE
UNTIL
. THEN

It may be ignored or not. For multiple loop-exits (avoiding
module-exits), each following WHILE is indented.

Don't ignore the CS-ROLL, so:

BEGIN
. WHILE
. . WHILE
. . . WHILE
UNTIL . .
. . . THEN
. . THEN
. THEN

Ignore the CS-ROLL, so:

BEGIN
WHILE
. WHILE
. . WHILE
. . UNTIL
. THEN
THEN

Just by indenting, more complex situations may become clear. Has any other
programming environment the capability to overlap loops?

BEGIN
. BEGIN [ 1 CS-ROLL ]
WHILE [ 2 CS-ROLL ]
. WHILE [ 2 CS-ROLL ]
UNTIL
. UNTIL [ 1 CS-ROLL ]
THEN
. THEN

Instead, Forth has definitely no GOTOs.

_Only_ count the C-stack contents for checking. Just _look_ at it for
comprehending what happens. Do not count. The graphics should make it clear:
This is two loops. Don't care for low level irritations...

Some craftmanship is involved: Insert the CS-ROLLS. Not all books are written
as trivial as the maintime TV news suggest.

A lot of execution flows will be controlled by more than one event. Many of
them _are_ structured, but are not trivial. Why ressort to a state machine, if
it is structured? A flow-graphics as above may show clearly what happens.

Thanx to the one who introduced the CS-PICK and -ROLL into Forth, or but the SO
and STILL as it has been named in a previous 'Basis' text (hope I got the names
right).

Ewald

W.Baden

unread,
Jul 31, 1996, 3:00:00 AM7/31/96
to

Anton Ertl (an...@a0.complang.tuwien.ac.at) wrote:

> These words are defined like this:

> [...]

"It's vain to do with more what can be done with fewer."

This is why I keep BUT around.

: BUT 1 CS-ROLL ; IMMEDIATE

CASE BEGIN
... IF
...
ELSE BUT
... IF
...
ELSE BUT
... IF
...
ELSE BUT
...
AGAIN THENS
--
Procedamus in pace. Wil Baden Costa Mesa, California

Ewald Pfau

unread,
Jul 31, 1996, 3:00:00 AM7/31/96
to

Since it may not seem obvious, for the following:

> BEGIN
> . WHILE
> . . WHILE
> . . . WHILE
> UNTIL . .
> . . . THEN
> . . THEN
> . THEN

let me add, that each THEN may be replaced by the pair ELSE .. THEN.

BEGIN
. WHILE
. . WHILE
. . . WHILE
UNTIL . .

. . . ELSE
. . . THEN
. . ELSE
. . THEN
. ELSE
. THEN

Ewald


zn...@teleport.com

unread,
Jul 31, 1996, 3:00:00 AM7/31/96
to

Bill Zimmerly (bi...@inlink.com) wrote:

: Bears are already scary enough, but dislexics interpreting

: the U.S. Constitution are even more scary.

Well, then you'll be interested in my view on gnu control. My motto is,
"No gnus is good news!".

--

Give me your brains or I'll blow your money out.

zn...@teleport.com

unread,
Jul 31, 1996, 3:00:00 AM7/31/96
to

Bill Zimmerly (bi...@inlink.com) wrote:

: zn...@teleport.com wrote:
: > ...[snip]
: > ...
: > 2. I rather like the Edsger Dijkstra guarded command syntax as developed
: > in "A Discipline of Programming". Now *there's* a book that's crying
: > out to be translated into Forth! I'm sure by now someone has
: > translated his *two* control structures into Forth -- I didn't see it
: > in my indexes of Forth Dimensions or FORML proceedings, though. If
: > no one has done it, I might be persuaded to use the ANS
: > "roll-your-own-control-structure" words (CS-ROLL, CS-PICK, AHEAD) to
: > do a sequentrial implementation without Dijkstra's non-deterministic
: > semantics.

: Excellent suggestion!
: - Bill

I spent a few hours on it, and decided to write it up as an article for
Forth Dimensions, since they are looking for articles on practical
experience with ANS Forth. After seeing the discussion on various
mixed-up and unreadable loops composed of the given ANS control flow
words, I'm really glad I coded them.

Actually, for their size, elephants don't smell all that bad.

"The only thing we have to fear is fear itself -- and, of course, the
boogeyman." Pat Paulsen

Stephen Pelc

unread,
Jul 31, 1996, 3:00:00 AM7/31/96
to

> In article <4so93r$d...@dfw-ixnews6.ix.netcom.com>, JETh...@ix.netcom.com
> (Jonah Thomas) writes:
> |> ... BEGIN ... WHILE ... WHILE ... WHILE ... REPEAT ... ELSE ... THEN ELSE
> ...
> |> THEN ;
May I take this opportunity to offer a construct which
a) takes advantage of words in common use
b) only requires one extra Forth word
The problem is to associate the multiple loop exit actions with
the exit conditions. The exampl above and its ilk do no achieve this
(IMHO).

Compare this with the currently common CASE ... ENDCASE structure
CASE
<condition1> OF <action> ENDOF
<condition2> OF <action> ENDOF
<condition3> OF <action> ENDOF
...
ENDCASE

We can turn this into loop with the following simple change
CASE
<condition1> OF <action> ENDOF
<condition2> OF <action> ENDOF
<condition3> OF <action> ENDOF
...
NEXTCASE
where NEXTCASE generates a branch to just after the CASE. Note that
the ENDOFs can still generate the same code as before, so exiting the
loop and continuing just after the NEXTCASE.
--
Stephen Pelc, s...@mpeltd.demon.co.uk
MicroProcessor Engineering - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 1703 631441, fax: +44 1703 339691

Paul E. Bennett

unread,
Jul 31, 1996, 3:00:00 AM7/31/96
to

In article <4tkmpa$3...@majipoor.cygnus.com>
a...@phal.cygnus.co.uk "Andrew Haley" writes:

> zn...@teleport.com wrote:
> : Wolfgang Allinger (A...@business.forth-ev.de) wrote:
> : : In forth words I use a lot of 'IF ... EXIT THEN' in the beginning to
> : : handle the special cases. A logic analyser is nearly useless in forth, so
> : : I do what it makes it easier for me.
>

> : Correct me if I'm wrong, but doesn't a logic analyzer operate by


> : sampling the busses and displaying instruction and data addresses? If
> : so, I'd think it would be possible to write your Forth code in a manner
> : that catered to this.
>

> That's not really the point. If you use Forth to develop embedded
> applications, a logic analyzer is redundant: you use interactivity
> instead of staring at traces. Interactivity is cheaper and more
> productive.
>

Actually Andrew, you should have said a logic analyser is "mostly" redundant
when using Forth for development. There may be some very rare case where the
use of one will be necessary. However, these occassions will be so rare that it
is not worth owning an analyser of ones own.


--
Paul E. Bennett <p...@transcontech.co.uk>
Transport Control Technology Ltd.
Tel: +44 (0)117-9499861
Going Forth Safely

Wolfgang Allinger

unread,
Jul 31, 1996, 3:00:00 AM7/31/96
to

On 29 Jul 96 in article <4tj4iq$h...@nadine.teleport.com>
<zn...@teleport.com> wrote:

>Wolfgang Allinger (A...@business.forth-ev.de) wrote:
snipp---


>: In forth words I use a lot of 'IF ... EXIT THEN' in the beginning
>to : handle the special cases. A logic analyser is nearly useless in
>forth, so : I do what it makes it easier for me.
>
>Correct me if I'm wrong, but doesn't a logic analyzer operate by
>sampling the busses and displaying instruction and data addresses?

Thats exactly the Problem, you trigger/trace on op-codes, you will see
always the NEXT, sometimes the NEST routine, if you trigger/trace the Data
stream, you cannot see the differences between data and cfa's. Also you
usually don't know the cfa's...

>If so, I'd think it would be possible to write your Forth code in a
>manner that catered to this.

I would be very happy, if somebody can show me a way!

>: --
>: FORTHing @ work Cheap
>: Fast Good ...pick any two of them

>I'll take *real* cheap and *real* fast!

Fine!

>I support the right to keep and arm bears.

That's even better!

Bye by Wolfgang

--
FORTHing @ work Cheap
Fast Good ...pick any two of them

Ewald Pfau

unread,
Aug 1, 1996, 3:00:00 AM8/1/96
to

[..]
SP> We can turn this into loop with the following simple change
SP> CASE
SP> <condition1> OF <action> ENDOF
SP> <condition2> OF <action> ENDOF
SP> <condition3> OF <action> ENDOF
SP> ...
SP> NEXTCASE
SP> where NEXTCASE generates a branch to just after the CASE. Note that
SP> the ENDOFs can still generate the same code as before, so exiting
SP> the loop and continuing just after the NEXTCASE.

This suggests either, not to use the C-stack for resolving forward branches or
to have an extra C-stack for resolving backwards branches. How can otherwise
the backwards branch be compiled, if the C-stack holds the references for the
implicit THENs?

OF compares two numbers to be equal. This is different from consuming a flag.
So it would be 'number1..' above instead of 'condition1..'. Or but you have a
special idea about OF..ENDOF?

It remained numbers even if we had SAME-OF, GREATER-OF, RANGE-OF...

Maybe, 'near' ELSEs (as compiled by ENDOF) are easier to be memorized than
'far' ELSEs. For execution flow, both are the same. It is a conditional branch
and an unconditional branch (the logical path differs). The latter ones, 'far'
ELSEs, may be compiled by what is given in ANS without an explicit CS-ROLL.

The difference is, to introduce an alternate path together with the conditional
to which it is an alternative, for 'near'. You think of it as having had an IF
and replace it by IF..ELSE. For 'far', the alternate path is introduced when
resolving the THENs. You think of it as having had THEN and replace it by
ELSE..THEN. By the latter one, you have to memorize, to which IF a THEN belongs
to. By use of a proper graphical layout, this may be as well easy.

For the 'near' ELSEs, Wil Baden showed his use of BUT. As I learnt meanwhile,
he was the one who once introduced the SO and STILL, which were replaced by the
more technical terms CS-PICK and CS-ROLL for ANS Forth then.

'near':
BEGIN
. IF end-01
. ELSE loop-01 [ 1 CS-ROLL ]
. IF end-02
. ELSE loop-02 [ 1 CS-ROLL ]
AGAIN
. THEN
. THEN

This results either from 'FLAG-OF .. ENDOF [ 1 CS-ROLL ]' or from 'IF .. ELSE
BUT'.

'far':
BEGIN
. WHILE loop-01
. WHILE loop-02
AGAIN
. ELSE end-02
. THEN
. ELSE end-01
. THEN

WHILE is 'IF [ 1 CS-ROLL ]'.

Ewald


Bernd Paysan

unread,
Aug 1, 1996, 3:00:00 AM8/1/96
to

Anton Ertl wrote:
> Of course, I would hide the low-level control-structure words behind
> new high-level words, e.g.:
>
> START
> ... IF
> ... LEAVE-LOOP
> ... IF
> ... LEAVE-LOOP
> ... IF
> ... LEAVE-LOOP
> ...
> END
>
> (yes, the names may not be optimal).

gforth provides this using

BEGIN BEGIN
... ?LEAVE
... ?LEAVE
... ?LEAVE
AGAIN DONE

so you simply define

: START postpone BEGIN postpone BEGIN ; immediate
: END postpone AGAIN postpone DONE ; immediate

The BUT mentioned by Will Baden is part of gforth, too. The other
control flow stack manipulator is YET, which is the equivalent of [ 1
CS-PICK ]. However, neither the BEGIN ... DONE trick (resolve LEAVEs
without a DO LOOP around them, found in Dr. Dobb's) nor the BUT/YET cs
effects are described in the gforth manual, so Anton is excused for not
knowing this...

Stephen Pelc

unread,
Aug 1, 1996, 3:00:00 AM8/1/96
to

In article <83889048...@ear.co.at> e...@ear.co.at "Ewald Pfau" writes:
> SP> We can turn this into loop with the following simple change
> SP> CASE
> SP> <condition1> OF <action> ENDOF
> SP> <condition2> OF <action> ENDOF
> SP> <condition3> OF <action> ENDOF
> SP> ...
> SP> NEXTCASE
> SP> where NEXTCASE generates a branch to just after the CASE. Note that
> SP> the ENDOFs can still generate the same code as before, so exiting
> SP> the loop and continuing just after the NEXTCASE.
> This suggests either, not to use the C-stack for resolving forward branches or
> to have an extra C-stack for resolving backwards branches. How can otherwise
> the backwards branch be compiled, if the C-stack holds the references for the
> implicit THENs?
For a traditional style of implementation, just reserve space for the branch
compilation, resolve the THENS, and then fill in the branch values.

> OF compares two numbers to be equal. This is different from consuming a flag.
> So it would be 'number1..' above instead of 'condition1..'. Or but you have a
> special idea about OF..ENDOF?

The Forth literature includes several modifications to the basic OF ...
ENDOF phrase. The most popular seems to be ?OF which takes a flag and
behaves like IF.

Please note that I am proposing this notation because it is visually
clean, keeps the <condition> code next to the <action> code, and thus
leads to more obvious and more maintainable code.

Ewald Pfau

unread,
Aug 2, 1996, 3:00:00 AM8/2/96
to

Stephen Pelc <s...@mpeltd.demon.co.uk> wrote:

[CASE..?OF..ENDOF..NEXTCASE]

SP> Please note that I am proposing this notation because it is visually
SP> clean, keeps the <condition> code next to the <action> code, and
SP> thus leads to more obvious and more maintainable code.

I suggested, this does not depend on the wording of the flowgraph words. It
depends on the sequence, where-to an ELSE is read to belong to. For RPN
notation, ELSEs fit more easy to the THENs. ANS Forth has means to deal with it
without CS-ROLLs.

For natural language, what you declare as 'obvious', leads to omit the need for
later-on referring.

(begin) Think of two things to happen.
(if) If yes for the first, so we're done.
(else) Elsewise,
(if) if yes for the second, so we're done.
(else) Elsewise,
(again) try again.
(then then) After having done the first or but the second...

To omit the referring just happens in everyday 'slang'. If it is to be
expressed precisely, so the reference is spelled as well (i.e. not suppose just
a 'nameless' series of THENs, but be aware of each one).

(begin) Think of two things to happen.
(while) If no for the first,
(while) if no for the second,
(again) try again.
(then) If yes for the second, we're done.
(else) If yes for the first, we're done.
(then)

The 'stacked' use of an ELSE is as common as the 'sequenced' use. Mostly it is
hidden among several words which give not the reading 'IF.. ELSE.. THEN' but
only have the meaning of it. Mass media tends to prefer the sequential use (in
fact, it suggests 'truths' which avoid the need to decide; as well listeners
are pretended to be too impatiened as to wait for the end of a sentence - but
'speedy' only seems obvious but it isn't by itself ...).

(this should be 'stacked' use):

Did you have to drink?
Did you have to eat?
If not, maybe you should eat something.
As well you should drink something, if you didn't.

Both constructs are 'obvious' (IF ELSE AGAIN THEN; IF AGAIN ELSE THEN).

***

The Forth words CASE, OF, ENDOF, ENDCASE are a separate set, which is not
related to the set of all other flowgraph words. By a CASE..ENDCASE construct,
a sequence of conditional and unconditional branches has to be compiled anyway.
The way of compilation is hidden and not very effective, so it cannot be
combined with more effective methods. As well it can hardly be combined with
other flowgraph words. It cannot be extended to fit special needs.

It will compile the same sequence of branches, as will a notation using IFs and
CS-ROLLS (or make a shortcut for '1 CS-ROLL' as has been put in here to read
'BUT').

Ok, it would be nice to extend the CASE..ENDCASE mechanism to a loop and offer
NEXTCASE. But if an implementation offers the CASE..ENDCASE construct, so it
cannot be extended by a ?OF (or a RANGE-OF or any-other-OF, or as well an
EXIT-ENDOF). The box with the building tools is sealed, so it makes for a weak
construct.

For more than, say, 5 cases, a more eficient method consists in having a
scanning word, having tables containing the criteria for comparison and for
execution. The cases machine does the scanning and the calculation of offsets
into the tables. This is to deal with data objects then, instead with code
consisting mainly of literals and of branches.

'Reading' means then, to start from the difference of a decision machine and of
decision data. This is for even better reading then...

(this is for 'objects reading') I have a set here, consisting of an apple, an
orange, a board and a rowing boat. If I grab one, so I need as well to bite, to
peel, to nail or to row.

Ewald


It is loading more messages.
0 new messages