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

Stack winding

8 views
Skip to first unread message

jace...@users.sourceforge.net

unread,
Apr 6, 2004, 4:59:45 AM4/6/04
to comp.la...@ada-france.org
Hi all,

What's the common name for this word?

: later 2r> swap 2>r ;

It is used to undo operations in the reverse order they were
done. Useful for things like allocations, opening files, and so on. An
example:

: setup-scr ." opening screen" cr later ." closing screen" cr ;
: setup-win ." opening window" cr later ." closing window" cr ;
: test setup-scr setup-window ;

Executing "test" would yield:

opening screen
opening window
closing window
closing screen

Greetings,
Jorge Acereda

Marcel Hendrix

unread,
Apr 6, 2004, 10:31:52 AM4/6/04
to
jace...@users.sourceforge.net writes Re: Stack winding

[..]

> What's the common name for this word?

> : later 2r> swap 2>r ;

: maintainer's_headache 2R> swap 2>R ;-)

[..]

-marcel

Guido Draheim

unread,
Apr 6, 2004, 8:59:22 AM4/6/04
to

agreed. ;-)

ward mcfarland

unread,
Apr 6, 2004, 8:36:27 AM4/6/04
to
<jace...@users.sourceforge.net> wrote:

I could see a word for a SWAP on the return stack, but if you plan to
use it primarily for that purpose, I would name it "DANGEROUS" or
"IMPLEMENTATIONDEPENDENT"

Astrobe

unread,
Apr 6, 2004, 12:29:43 PM4/6/04
to
jace...@users.sourceforge.net wrote in message news:<mailman.191.108124200...@ada-france.org>...


IIRC this is CO ( IIRC it has to do with co-routines )

Amicalement,
Astrobe

" That's too obvious to be true "

Julian V. Noble

unread,
Apr 6, 2004, 12:45:56 PM4/6/04
to

If you want reverse the order order of a sequence of operations,
use a LIFO (Last-In, First-Out) buffer. Sometimes called a stack.
They are especially easy to define in Forth. And for the uses you
suggest, a separate stack sounds like a smart idea.

--
Julian V. Noble
Professor Emeritus of Physics
j...@lessspamformother.virginia.edu
^^^^^^^^^^^^^^^^^^
http://galileo.phys.virginia.edu/~jvn/

"For there was never yet philosopher that could endure the
toothache patiently."

-- Wm. Shakespeare, Much Ado about Nothing. Act v. Sc. 1.

Federico de Ceballos

unread,
Apr 6, 2004, 2:34:51 PM4/6/04
to comp.la...@ada-france.org
Jorge,

> : later 2r> swap 2>r ;

> : setup-scr ." opening screen" cr later ." closing screen" cr ;
> : setup-win ." opening window" cr later ." closing window" cr ;

> : test setup-scr setup-win ;

_test_ doesn't work with tail optimization (as in SwiftForth). In any
case, I don't think it is clear enough. Furthermore, it would be
difficult to test a word when something else is expected between the
two parts. How about something in the line of:

: /scr ." opening screen" cr ;
: scr/ ." closing screen" cr ;
: /win ." opening window" cr ;
: win/ ." closing window" cr ;
: test /scr /win win/ scr/ ;

Regards,

Federico de Ceballos


Jeff Fox

unread,
Apr 7, 2004, 12:34:37 AM4/7/04
to
> Hi all,
>
> What's the common name for this word?
>
> : later 2r> swap 2>r ;

Piss-off-the-ANS-Forth-programmers-who-can't... ?
Ask-ANS-Forth-programmers-to-insult-you ?
Ask-to-be-lectured-about-'modern'-Forth ?
Traditional-style-co-routine ?
CO ?

(Silly of you to ask in c.l.f without checking the archives
on the subject. Been discussed here before. But still fun.)

The obvious real problem is that it requires a real return
stack, it requires two stacks, and ANS warns that you cannot
expect that in ANS Forth. Some will tell you that you should
simply not do that, others will suggest that maybe you need
to define another stack to be able to do it in a 'portable'
way. ;-)

Best Wishes

Jeff Fox

unread,
Apr 7, 2004, 12:40:14 AM4/7/04
to
"Federico de Ceballos" <federico...@unican.es> wrote in message news:<mailman.195.108127650...@ada-france.org>...

> Jorge,
>
> > : later 2r> swap 2>r ;
> > : setup-scr ." opening screen" cr later ." closing screen" cr ;
> > : setup-win ." opening window" cr later ." closing window" cr ;
> > : test setup-scr setup-win ;
>
> _test_ doesn't work with tail optimization (as in SwiftForth). In any
> case, I don't think it is clear enough. Furthermore, it would be
> difficult to test a word when something else is expected between the
> two parts.

If you want to do the above and have to work around a tail
optimizer try adding NOP or something that won't get tail optimized
before the final semicolon. (if you can't just turn it off ;-)
Without that you might get jumps to CR instead of calls to CR, and
a jump to setup-win instead of a call would also cause failure.
Inlining optimization might also mess up this sort of traditional
threaded Forth style code.

Best Wishes

jace...@users.sourceforge.net

unread,
Apr 7, 2004, 7:41:38 AM4/7/04
to comp.la...@ada-france.org
jace...@users.sourceforge.net writes:

> Hi all,
>
> What's the common name for this word?
>

> : later 2r> swap 2>r ;

There has been a lot of negative reactions to this question. Let me
explain and ask the question again.

I didn't ask this to discuss how portable, how easy to maintain or how
beautiful it is. I was also aware of the existence of the CO word. I
simply don't see this usage as something along the lines of CO. CO is
normally used when you have several processes (sort of) cooperating
(producer/consumer and friends...). For me, CO and LATER share the
implementation, but the semantics are different.

In this case, it is used to delay the execution of the remaining of
the word until the program finishes. So, is there any other name for
CO assuming this semantics?

Greetings,
Jorge Acereda

jmdrake

unread,
Apr 7, 2004, 11:21:30 AM4/7/04
to
"Federico de Ceballos" <federico...@unican.es> wrote in message news:<mailman.195.108127650...@ada-france.org>...
> Jorge,
>
> > : later 2r> swap 2>r ;
> > : setup-scr ." opening screen" cr later ." closing screen" cr ;
> > : setup-win ." opening window" cr later ." closing window" cr ;
> > : test setup-scr setup-win ;
>
> _test_ doesn't work with tail optimization (as in SwiftForth).

It works in Win32Forth and bigForth. Perhaps this is a good word
for testing what you can/can't do with the return stack in a particular
implementation of ANS Forth.

Regards,

John M. Drake

Anton Ertl

unread,
Apr 7, 2004, 10:38:03 AM4/7/04
to

Looking at the example, it looks like there is some potential to be
the literate maintainer's delight.

: setup-scr ." opening screen" cr later ." closing screen" cr ;
: setup-win ." opening window" cr later ." closing window" cr ;
: test setup-scr setup-window ;

As usual, any technique that the maintainer is not familiar with will
cause him headaches, but that's no reason to stop investigating and
adopting new techniques.

BTW, some time ago in maintenance mode I came across stuff like this
in the Gforth sources:

: ...
... >stderr ." ..." ;

This struck me as funny, because, while >stderr seemed to redirect the
output, I could see no restoration of the old direction. Looking at
>stderr, I found:

: >stderr ( -- )
r> outfile-id >r stderr to outfile-id
>exec r> to outfile-id ;

: >exec >r ; restrict ( :-)

After a little bit of head-scratching, I realized what this is doing
(basically a variant of the LATER technique). So it is possible to
maintain such code even if you are unfamiliar with the technique.

So, what I am interested in is: What can be done with this technique?
What are the restrictions on its use? What are the alternatives? Are
the benefits big enough to make learning and teaching it worthwhile?

Jorge Acereda writes:
|It is used to delay the execution of the remaining of the word until
|the program finishes.

What it actually does is to delay the execution until the caller
finishes, which is probably better anyway.

What I don't like about LATER and >EXEC is that they fail in the
presence of exceptions:

: test2 setup-scr setup-win abort ; ok
test2

prints:

opening screen
opening window

*the terminal*:9: Aborted
...

Can we fix this? Probably with carnal knowledge of the implementation
of exceptions, but probably not in a mostly-portable fashion like the
original LATER. Or maybe we can: something along the lines of

: later ( -- ) \ untested
r> r> swap >r build-xt catch
r> >exec throw ;

This uses the trick twice, once for the restoration code, and once for
the THROW. The difficulty here is the BUILD-XT part, i.e., how to get
from a return address to an execution token that perform the code at
the return address. Any ideas?

The other thing that I don't like about this technique is that you can
only get back to the original state by exiting the word. I'd prefer
to be able to get back by having a special end word, as in:

: foo ( -- )
>stderr ." some warning" end< ." some other text" ;

or

: bar ( -- )
setup-scr setup-win end< ." do something else before returning" cr ;

Hmm, that might be possible:

: end< ( -- )
2r> swap 2>r ;

Finally, I see problems for some implementations of locals (Gforth
should be fine as long as you don't use locals in the words that
directly contain LATER).

Simple tail-call optimization alone should be no problem (except for
TEST), because for the usual usage you will always have code following
LATER, END<, and the words using LATER, like OPEN-WIN. More
sophisticated optimizations (e.g., inlining) could be a problem.

What are the alternatives in ANS Forth (with proper exception
handling):

: setup-scr ( xt -- )
." opening screen" cr
catch
." closing screen" cr
throw ;

: setup-win ( xt -- )
." opening window" cr
catch
." closing window" cr
throw ;

: test1 ( -- )
['] noop setup-win ;

: test ( -- )
['] test1 setup-scr ;

The definition of TEST and TEST1 are not really showcases of
readability.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html

Jeff Fox

unread,
Apr 7, 2004, 1:09:47 PM4/7/04
to
jace...@users.sourceforge.net wrote in message news:<mailman.204.108133811...@ada-france.org>...

> I didn't ask this to discuss how portable, how easy to maintain or how
> beautiful it is.

That's what you thought! Certainly you knew that it was not
recommended in ANS Forth and expected those topics to come up here.



> In this case, it is used to delay the execution of the remaining of
> the word until the program finishes. So, is there any other name for
> CO assuming this semantics?

If you do a google advanced newsgroups search on comp.lang.forth for
the phrase "2r> swap 2>r" you will see that it has been given a
couple of names other than LATER or CO. But I for one don't see that
the other names are better than your name LATER.

Best Wishes

Marcel Hendrix

unread,
Apr 7, 2004, 1:39:45 PM4/7/04
to
an...@a0.complang.tuwien.ac.at (Anton Ertl) writes Re: Stack winding

> m.a.m....@tue.nl (Marcel Hendrix) writes:
>>jace...@users.sourceforge.net writes Re: Stack winding

>>[..]

>>> What's the common name for this word?

>>> : later 2r> swap 2>r ;

>>: maintainer's_headache 2R> swap 2>R ;-)

> Looking at the example, it looks like there is some potential to be
> the literate maintainer's delight.

> : setup-scr ." opening screen" cr later ." closing screen" cr ;
> : setup-win ." opening window" cr later ." closing window" cr ;
> : test setup-scr setup-window ;

:-) You seem not to have looked too closely at this code, as it should be:

: test setup-scr setup-win ; \ <-- note "dow"

FORTH> : later 2r> swap 2>r ; ok
FORTH> : setup-scr ." opening screen" cr later ." closing screen" cr ; ok
FORTH> : setup-win ." opening window" cr later ." closing window" cr ; ok
FORTH> : test setup-scr setup-win ; ok
FORTH> cr test


opening screen
opening window
closing window
closing screen

So at least *this example* can work on an ANS Forth.

> As usual, any technique that the maintainer is not familiar with will
> cause him headaches, but that's no reason to stop investigating and
> adopting new techniques.

Ok, true.

> BTW, some time ago in maintenance mode I came across stuff like this
> in the Gforth sources:

> : ...
> ... >stderr ." ..." ;

> This struck me as funny, because, while >stderr seemed to redirect the
> output, I could see no restoration of the old direction. Looking at
> >stderr, I found:

[..]

> After a little bit of head-scratching, I realized what this is doing
> (basically a variant of the LATER technique). So it is possible to
> maintain such code even if you are unfamiliar with the technique.

What if it had been
: BAR
... >stderr FOO ;

And FOO was maintained by somebody else? Would it be possible to change
FOO using only standard code so that BAR stops working?

> So, what I am interested in is: What can be done with this technique?
> What are the restrictions on its use? What are the alternatives? Are
> the benefits big enough to make learning and teaching it worthwhile?

[ shows a snag of the FOO type ]
[..]

> What are the alternatives in ANS Forth (with proper exception
> handling):

> : setup-scr ( xt -- )
> ." opening screen" cr
> catch
> ." closing screen" cr
> throw ;

Nice! I use this technique (xt passing) fairly often, as in:

: setup-win ( xt -- )

CR ." opening window"
execute
CR ." closing window" ;

FORTH> ' cr setup-win
opening window

closing window ok
FORTH> ' .s cr setup-win

opening window
Data: ---
System: ---
Float: ---
closing window ok

.. but this catch/throw variant is nicer and very easy to understand.

-marcel

jonah thomas

unread,
Apr 7, 2004, 3:02:02 PM4/7/04
to
jmdrake wrote:
> "Federico de Ceballos" <federico...@unican.es> wrote

>>>: later 2r> swap 2>r ;


>>>: setup-scr ." opening screen" cr later ." closing screen" cr ;
>>>: setup-win ." opening window" cr later ." closing window" cr ;
>>>: test setup-scr setup-win ;

>>_test_ doesn't work with tail optimization (as in SwiftForth).

> It works in Win32Forth and bigForth. Perhaps this is a good word
> for testing what you can/can't do with the return stack in a particular
> implementation of ANS Forth.

I wondered whether there might be a way to get a similar effect that
doesn't need the return stack. Here's my third attempt:

: LATER::
:NONAME ;
: later
POSTPONE ; :NONAME ;
: ;LATER|
CREATE , , IMMEDIATE
DOES>
DUP CELL+ @ COMPILE,
' COMPILE,
@ COMPILE, ;

It's clumsier.

LATER:: ." opening screen" cr


later ."closing screen" cr

:LATER| setup-scr

Maybe there's a way to clean up the syntax.

This does have the value that you can do anything you like to the
return stack and it won't interfere with later.

But there are minor gotchas in return, setup-scr setup-win have to be
on the same line, you can't have a line break between them, setup-win
had better not be immediate, etc.

With the gotchas so different it might be better for them to have
different names. In a pinch you might use something like this later
on a system where the other doesn't work, but you'd have to change
ever place in the code that contains a later and there could still be
bugs.

Michael L Gassanenko

unread,
Apr 7, 2004, 7:05:42 PM4/7/04
to

What can be done with it?
Backtracking.

And other things such as co-routines.
There's a technique called "data execution" or "data-driven approach".
You represent the data in an executable form and then let the code
interpreter process it.

IMO, the right way to factor it is not
: ??? R> R> SWAP >R >R :
but
: ENTER >R ;
and
R@ ENTER
or
R> ENTER
or
R'@ ENTER
. For example,

: ENTER >R ; \ I already have it in my system
*** ENTER already defined, cfa=4001810h(67115024) ok[Dec]
: 1-20 1 BEGIN DUP 21 < WHILE >R 2R@ SWAP ENTER R> 1+ REPEAT DROP RDROP ;
ok[Dec]
: foo 1-20 . ;
ok[Dec]
foo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ok[Dec]
: //2 DUP 2 MOD 0= IF R@ ENTER ELSE DROP THEN RDROP ;
ok[Dec]
: //3 DUP 3 MOD 0= IF EXIT THEN DROP RDROP ;
ok[Dec]
: foo2 1-20 //2 . ;
ok[Dec]
foo2
2 4 6 8 10 12 14 16 18 20 ok[Dec]
: foo3 1-20 //3 . ;
ok[Dec]
foo3
3 6 9 12 15 18 ok[Dec]
: foo6 1-20 //3 //2 . ;
ok[Dec]
foo6
6 12 18 ok[Dec]


Another example -- printing all subsets of a set.
It assumes that the stack is initially empty and uses
.S for printing a set... of course, it's a simplification,
but then it's a toy problem:

: el R@ ENTER DROP ;
ok[Dec]
: .subsets 10 el 20 el 33 el .S ;
ok[Dec]
.subsets

[3] 10 20 33 ;
[2] 10 20 ;
[2] 10 33 ;
[1] 10 ;
[2] 20 33 ;
[1] 20 ;
[1] 33 ;
stack empty ok[Dec]

So if you can understand how it works, then such techniques are
maintainable and do not listen to those who tells you the reversal.

There's another problem: people believe that only straightforward
code is maintainable. That is, you have to write so that a fool can
understand it. OTOH, a fool will not be able to maintain the code
anyway: he will introduce additional variables until it becomes
impossible to understand what state the program is in.

On the third hand, straightforward code *is* more easy
to reuse by copy & paste. If you define

: foo this that and ;

and get

: foo this that and ;
: bar1 bla11 bla12 foo ;
: bar2 bla21 bla22 foo ;
: bar3 bla31 bla32 foo ;

this code is more difficult to reuse than

: bar1 bla11 bla12 this that and ;
: bar2 bla21 bla22 this that and ;
: bar3 bla31 bla32 this that and ;

because in the latter case you have to copy 1 code fragment
if you want to reuse just bar2 and bar3; in the first case,
you have to copy 2 code fragments: a definition of foo
and the definitions of bla2 and bla3.

Things get even worse if you use 2 auxiliary definitions...

So what we finally get? "Factoring considered harmful".


Proving that *any* advanced technique may be considered
harmful is left as an exercise for the reader.


--
BEGIN
- "Programs must be commented in Russian, because English
is difficult to understand."
- "No, programs must be commented in English, because Cyrillic
letters become unreadable when the system glitches."
AGAIN

(not sure whether I will post to this thread again
and thus have a chance to use another sig:
--
"the code is so straightforward that it is offensive to the maintainer"
)

Albert van der Horst

unread,
Apr 7, 2004, 11:49:57 AM4/7/04
to
In article <b2ebfb5f.04040...@posting.google.com>,

That is iff it obeys the following description.

--------------------------------

CO
--

Name: `CO'

No stackeffect

Attributes:

Description: Return, suspending interpretation of the current definition,
such that when the caller exits, this definition is resumed. The return
stack must not be engaged, such as between `>R' and `R>' , or `DO'
and `LOOP' .

See also: `EXIT'
--------------------------------

There is no guarantee that the given word -- LATER -- is a proper
implementation of CO (which triggered the comments that it would
be useless or dangerous.)
Note that the remark about the return stack defines the limitations
for this word for a particular implementation (in this case ciforth.).

CO is a very useful word, albeit not very often needed.
I use it once in a library to incorporate the old behaviour of a
word in a redefinition. And once in the MANX2 program to have data
available that was already compiled. And plan to use if for local
variables, if I ever need them.

Whenever you need it, it solves a problem that is hard to solve
differently.

>
> Amicalement,
> Astrobe

Groetjes Albert.

--
Albert van der Horst,Oranjestr 8,3511 RA UTRECHT,THE NETHERLANDS
One man-hour to invent,
One man-week to implement,
One lawyer-year to patent.

jace...@users.sourceforge.net

unread,
Apr 8, 2004, 5:57:22 AM4/8/04
to Albert van der Horst, comp.la...@ada-france.org
Hi Albert,

alb...@spenarnc.xs4all.nl (Albert van der Horst) writes:

<Talking about CO>

> And plan to use if for local variables, if I ever need them.

Could you ellaborate on that?

Stephen Pelc

unread,
Apr 8, 2004, 6:12:55 AM4/8/04
to comp.lang.forth
On 7 Apr 2004 16:05:42 -0700, m_l...@yahoo.com (Michael L Gassanenko)
wrote:

>So if you can understand how it works, then such techniques are
>maintainable and do not listen to those who tells you the reversal.

The chances of understanding are much improved by extensive
commenting or documentation in the source code. They are
also improved by suitable choice of word names, even if these
are simply renamings.

In the case of LATER, the assumption that return addresses are
on the return stack was unstated. Michael has proposed using
RA as an indicator for this. It is an unfortunate side-effect
of ANS Forth that such techniques are sometimes disparaged.

: later \ -- : resume in CALLER'S CALLER
\ Document assumptions here
ra> ra> swap >ra >ra
;

Some code just *is* difficult to understand, and Forth seems
to enable use of difficult (rare?) techniques more than most
other languages.

This particular example should not be discouraged, it should
instead be documented and placed in a system layer rather
than an application layer. I would rather call this word
some thing like
;LATER:
[LATER]
to indicate that something startling will happen.

>There's another problem: people believe that only straightforward
>code is maintainable. That is, you have to write so that a fool can
>understand it. OTOH, a fool will not be able to maintain the code
>anyway: he will introduce additional variables until it becomes
>impossible to understand what state the program is in.

Being involved in very large Forth apps (850+k LOC) managed
in a surgical team approach, I find the use of the word fool
rather derogatory. The top level application programmers have
skills that I as a system programmer do not have. They do not
have the system skills that I have.

>On the third hand, straightforward code *is* more easy
>to reuse by copy & paste.

It has been said that there are three types of function
call:
call by value
call by reference
call by text editor

In a Forth environment, call by text editor is pernicious. I
believe that some of the excessive tool support, especially
in editors, is a result of having to maintain "call by text
editor" code.

MPE's switchable prefix/postfix assemblers depend on techniques
such as that used in Jorge's LATER. Making these techniques
maintainable in large applications is a management issue.

Stephen

--
Stephen Pelc, steph...@INVALID.mpeltd.demon.co.uk
MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691
web: http://www.mpeltd.demon.co.uk - free VFX Forth downloads

jace...@users.sourceforge.net

unread,
Apr 8, 2004, 7:48:11 AM4/8/04
to Albert van der Horst, comp.la...@ada-france.org
jace...@users.sourceforge.net writes:

> Hi Albert,
>
> alb...@spenarnc.xs4all.nl (Albert van der Horst) writes:
>
> <Talking about CO>
>

> > And plan to use if for local variables, if I ever need them.
>

> Could you ellaborate on that?

Oops, sorry. You already did in the "Return stack ops" thread.

Albert van der Horst

unread,
Apr 8, 2004, 8:46:54 AM4/8/04
to
In article <2004Apr...@a0.complang.tuwien.ac.at>,
Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
<SNIP>

>As usual, any technique that the maintainer is not familiar with will
>cause him headaches, but that's no reason to stop investigating and
>adopting new techniques.
>
>BTW, some time ago in maintenance mode I came across stuff like this
>in the Gforth sources:
>
>: ...
> ... >stderr ." ..." ;
>
>This struck me as funny, because, while >stderr seemed to redirect the
>output, I could see no restoration of the old direction. Looking at
>>stderr, I found:
>
>: >stderr ( -- )
> r> outfile-id >r stderr to outfile-id
> >exec r> to outfile-id ;

Or
: >stderr out-file stderr TO out-file-id CO TO out-file ;

\ To get the file-descriptor out of the way Marcel Hendrix would do
: >stderr out-file >S stderr TO out-file-id CO S> TO out-file ;

\ Tucking under the return address obscures the code somewhat.
: >stderr
R> out-file >R >R
stderr TO out-file-id CO
R> R> TO out-file >R ;

>: >exec >r ; restrict ( :-)
>
>After a little bit of head-scratching, I realized what this is doing
>(basically a variant of the LATER technique). So it is possible to
>maintain such code even if you are unfamiliar with the technique.
>
>So, what I am interested in is: What can be done with this technique?
>What are the restrictions on its use? What are the alternatives? Are
>the benefits big enough to make learning and teaching it worthwhile?

There are no alternatives, really. If you need it, you need it badly.

<SNIP>


>What I don't like about LATER and >EXEC is that they fail in the
>presence of exceptions:
>
>: test2 setup-scr setup-win abort ; ok
>test2
>
>prints:
>
>opening screen
>opening window
>
>*the terminal*:9: Aborted

>....

As far as I can see, this is exactly the behaviour I want.
What do you want?

<SNIP>

>- anton
Groetjes Albert

Albert van der Horst

unread,
Apr 8, 2004, 10:11:19 AM4/8/04
to

I don't think so, (unless I read this "some ANS Forth".)
As Jef Fox has pointed out repeatedly,
there is no requirement in ISO that the return stack contains
return addresses or is in any way related to return behaviour.

Then LATER would only give a "return stack underflow" error.
If the return stack was used for loop indices, things would mess up
real bad indeed.

>-marcel
Groetjes Albert.

jonah thomas

unread,
Apr 8, 2004, 9:08:51 PM4/8/04
to
Albert van der Horst wrote:
> Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:

>>So, what I am interested in is: What can be done with this technique?
>>What are the restrictions on its use? What are the alternatives? Are
>>the benefits big enough to make learning and teaching it worthwhile?

> There are no alternatives, really. If you need it, you need it badly.

What about my alternative that changes things at compile-time rather
than swapping the return stack?

The way I wrote it doesn't nest, but it could be done nestably.

Michael L Gassanenko

unread,
Apr 9, 2004, 5:28:47 PM4/9/04
to
steph...@INWALID.mpeltd.demon.co.uk (Stephen Pelc) wrote in message news:<40751cf2....@192.168.0.1>...

> On 7 Apr 2004 16:05:42 -0700, m_l...@yahoo.com (Michael L Gassanenko)
> wrote:
> >There's another problem: people believe that only straightforward
> >code is maintainable. That is, you have to write so that a fool can
> >understand it. OTOH, a fool will not be able to maintain the code
> >anyway: he will introduce additional variables until it becomes
> >impossible to understand what state the program is in.
> Being involved in very large Forth apps (850+k LOC) managed
> in a surgical team approach, I find the use of the word fool
> rather derogatory. The top level application programmers have
> skills that I as a system programmer do not have. They do not
> have the system skills that I have.

These were impressions from a small C project in a mainstream
organization.

> the use of the word fool
> rather derogatory.

"we are writing not for ourselves"

Well, the mainstream-oriented folks really do have a different
attitude towards coding. They are used to straightforward
solutions. For them, straightforward is *the norm*.
With Forth, the solution begins from thinking.
So condensed, laconic, even cryptic, is the norm.

The essence of the C project was tranlation of the documentation
from English (with examples in C and/or Basic) into C
for the particular case of interest. Receive some arguments
and structures from the system, make some assignments,
and pass them to some other functions.

I do not even think that Forth would make a good choice
for that task.

Albert van der Horst

unread,
Apr 9, 2004, 7:47:46 AM4/9/04
to
In article <XLmdc.156$RR1....@news.uswest.net>,

Most of the time you will use CO for general tools, one level
up from your application example. For this goal your way is too
invasive.

An example where I think it would be hard to impossible to use your
alternative is the well known LOCALS example (also in one of my Forth
lectures.) You don't want to burden the user of LOCALS with the
requirement to call DEALLOCATE-LOCALS just before the semi colon.
If you want to make LOCALS a loadable extension, I can't think
of an alternative.

Another example.
In the -t option of ciforth compilation is tried with possible insecure
means. When an error is detected of the sort that something is undefined,
an attempt is made to load the undefined thingy from a library.
The error recovery consists of
(note that we are in the middle of compiling a definition X, and
that this code is patched into the error-detection routines).
NESTED-COMPILE[ \ Store state of library chain.
REQUIRE-THINGY \ Load from library if possible.
NESTED-COMPILE] \ Restore information that we are compiling X
(You also need THEN .. ELSE similar code to jump over the dictionary
space used up. )
Now this sequence is beter replaced by
NESTED-COMPILE REQUIRE-THINGY
And NESTED-COMPILE looks like
: NESTED-COMPILE
NESTED-COMPILE[ ( written out)
CO
NESTED-COMPILE] ( written out)
;
This makes it easier to use (because one call is done),
easier to document (because there are no requirements like use
these in pairs), easier to check (because what is saved and restored
appears together in one definition), and easier to implement (because
storing is on the return stack).

Groetjes Albert
--

Anton Ertl

unread,
Apr 10, 2004, 8:29:01 AM4/10/04
to
m...@iae.nl (Marcel Hendrix) writes:
>an...@a0.complang.tuwien.ac.at (Anton Ertl) writes Re: Stack winding
>> Looking at the example, it looks like there is some potential to be
>> the literate maintainer's delight.
>
>> : setup-scr ." opening screen" cr later ." closing screen" cr ;
>> : setup-win ." opening window" cr later ." closing window" cr ;
>> : test setup-scr setup-window ;
>
>:-) You seem not to have looked too closely at this code, as it should be:
>
>: test setup-scr setup-win ; \ <-- note "dow"

The evils of using the Forth command line instead of using files: I
ended up with various "ok"s, and, in this case, an error message and
retry interspersed, so I didn't want to copy from there into the
article, so I copied from the original article, forgetting to correct
the error.

>> After a little bit of head-scratching, I realized what this is doing
>> (basically a variant of the LATER technique). So it is possible to
>> maintain such code even if you are unfamiliar with the technique.
>
>What if it had been
>: BAR
> ... >stderr FOO ;

What about it?

>And FOO was maintained by somebody else? Would it be possible to change
>FOO using only standard code so that BAR stops working?

Well, of course. When is this ever not possible.

If you mean, if FOO could be changed to break the restoration aspect
of BAR, only THROWing would break that.

Anton Ertl

unread,
Apr 10, 2004, 8:38:37 AM4/10/04
to
alb...@spenarnc.xs4all.nl (Albert van der Horst) writes:
>In article <2004Apr...@a0.complang.tuwien.ac.at>,
>Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
>>So, what I am interested in is: What can be done with this technique?
>>What are the restrictions on its use? What are the alternatives? Are
>>the benefits big enough to make learning and teaching it worthwhile?
>
>There are no alternatives, really. If you need it, you need it badly.

I presented one alternative. But maybe it's not real:-)

><SNIP>
>>What I don't like about LATER and >EXEC is that they fail in the
>>presence of exceptions:
>>
>>: test2 setup-scr setup-win abort ; ok
>>test2
>>
>>prints:
>>
>>opening screen
>>opening window
>>
>>*the terminal*:9: Aborted
>>....
>
>As far as I can see, this is exactly the behaviour I want.
>What do you want?

I want the setup to be reverted when test2 is left. I.e.:

opening screen
opening window
closing window
closing screen

*the terminal*:9: Aborted

In the present example, you may not see the problem of not doing the
cleanup on throwing. But consider cases like:

: setup-base ( -- )
base @ { old-base } hex later old-base base ! ;

or

: bla
100 0 do
... ['] test2 catch ...
loop ;

jonah thomas

unread,
Apr 10, 2004, 2:13:07 PM4/10/04
to
Albert van der Horst wrote:
> jonah thomas <j2th...@cavtel.net> wrote:
>>Albert van der Horst wrote:
>>>Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:

>>>>So, what I am interested in is: What can be done with this technique?
>>>>What are the restrictions on its use? What are the alternatives? Are
>>>>the benefits big enough to make learning and teaching it worthwhile?

>>>There are no alternatives, really. If you need it, you need it badly.

>>What about my alternative that changes things at compile-time rather
>>than swapping the return stack?

> Most of the time you will use CO for general tools, one level


> up from your application example. For this goal your way is too
> invasive.

I don't understand. You're doing it from source code anyway, right?

> An example where I think it would be hard to impossible to use your
> alternative is the well known LOCALS example (also in one of my Forth
> lectures.) You don't want to burden the user of LOCALS with the
> requirement to call DEALLOCATE-LOCALS just before the semi colon.
> If you want to make LOCALS a loadable extension, I can't think
> of an alternative.

I may have misunderstood about this. An obvious way to do that is

: : 0 ; \ have : add a flag to its colon-sys

: LOCAL \ whatever name you want to use
1+ POSTPONE LOCAL ; IMMEDIATE \ set the flag

: ;
IF POSTPONE DEALLOCATE-LOCALS THEN
POSTPONE ; ; IMMEDIATE

This calls DEALLOCATE-LOCALS just before ; provided you use locals.
It requires that you set up locals right after : or at least before
you do anything else that affects the control-flow stack like IF or DO .

It doesn't handle EXIT . EXIT would be used inside control-flow
structures. You could put the flag in a variable instead of a stack
provided you don't do nested definitions like

: FOO SETUP AHEAD [ : BAR STUFF ; ] THEN FINAL ;

If DEALLOCATE-LOCALS can tell whether it needs to act -- if the top
return-stack item is a specific value for locals that can't be
confused with a legitimate return value -- then we could just accept a
slight penalty and do

: ;
DEALLOCATE-LOCALS POSTPONE ; ; IMMEDIATE
: EXIT
DEALLOCATE-LOCALS EXIT ;
or
: EXIT
POSTPONE DEALLOCATE-LOCALS POSTPONE EXIT ; IMMEDIATE
or something like that.

The redefinitions in any case would go into the loadable extension,
which would only be used to define words that need locals.

There could be a penalty to doing it this way, but I don't see that
it's hard to impossible.

> Another example.
> In the -t option of ciforth compilation is tried with possible insecure
> means. When an error is detected of the sort that something is undefined,
> an attempt is made to load the undefined thingy from a library.
> The error recovery consists of
> (note that we are in the middle of compiling a definition X, and
> that this code is patched into the error-detection routines).
> NESTED-COMPILE[ \ Store state of library chain.
> REQUIRE-THINGY \ Load from library if possible.
> NESTED-COMPILE] \ Restore information that we are compiling X
> (You also need THEN .. ELSE similar code to jump over the dictionary
> space used up. )
> Now this sequence is beter replaced by
> NESTED-COMPILE REQUIRE-THINGY
> And NESTED-COMPILE looks like
> : NESTED-COMPILE
> NESTED-COMPILE[ ( written out)
> CO
> NESTED-COMPILE] ( written out)
> ;
> This makes it easier to use (because one call is done),
> easier to document (because there are no requirements like use
> these in pairs), easier to check (because what is saved and restored
> appears together in one definition), and easier to implement (because
> storing is on the return stack).

I don't see why this would be a problem with the way I did it. CO may
be simpler, but it also brings in some special limitations. It looks
like an esthetic choice to me.

You could do something like:

( CO system will make words that compile 3 xt's each, a preamble, a
second word that is found in the input stream, and a postamble. )

( G: build CO datastructure, start preamble )
: CO:
CREATE HERE 0 , 0 , IMMEDIATE :NONAME

( G: child will compile preamble, get next word and handle it,
then compile postamble )
DOES>
DUP >R \ protect the address from immediate words, unneeded?
@ COMPILE,
BL WORD FIND 1+ IF EXECUTE ELSE COMPILE, THEN \ no not-word check
R> CELL+ @ COMPILE, ;

( G: store the preamble xt, and start the postamble definition )
: CO ( addr colon-sys1 -- addr colon-sys2 )
POSTPONE ; OVER !
:NONAME ; IMMEDIATE

( G: store the postamble xt )
: ;CO ( addr colon-sys -- )
POSTPONE ; SWAP CELL+ ! ; IMMEDIATE

CO: FOO
." FOO preamble " CO ." FOO postamble " ;CO

: TESTPHRASE ." HELLO" ;
: ANOTHERPHRASE ." GOODBYE" ;
: TEST
FOO TESTPHRASE FOO ANOTHERPHRASE ;

I haven't tested this but something very similar should work.

It has no unusual effects on the return stack. If you do

: TEST1
FOO DO I . LOOP ;
10 1 TEST1

You should get
FOO preamble FOO postamble 1 FOO postamble 2 FOO postamble 3 ...
FOO postamble 9

It does require that FOO not be at the end of a line, and that the
next word be an executable and not a number.

Have I misunderstood what you're trying to do?

Albert van der Horst

unread,
Apr 11, 2004, 7:16:05 AM4/11/04
to
In article <7TWdc.17$m32....@news.uswest.net>,

Of course. That is the alternative I can't think of. Maybe I should
have said "want not".
I just studied a locals implementation (for ciforth) somebody sent to
me. It was set up such that you could redefine EXIT and he did.
Then I read up about LOCALS in the ANS manual, and realised that
DOES> must be redefined too. The CO solution handles this
automagically. More importantly, you need no longer redefine : .

>If DEALLOCATE-LOCALS can tell whether it needs to act -- if the top
>return-stack item is a specific value for locals that can't be
>confused with a legitimate return value -- then we could just accept a
>slight penalty and do
>
>: ;
> DEALLOCATE-LOCALS POSTPONE ; ; IMMEDIATE
>: EXIT
> DEALLOCATE-LOCALS EXIT ;
>or
>: EXIT
> POSTPONE DEALLOCATE-LOCALS POSTPONE EXIT ; IMMEDIATE
>or something like that.

Again you overlooked DOES> . Are you sure there isn't more you
overlook?

>The redefinitions in any case would go into the loadable extension,
>which would only be used to define words that need locals.

True. They could even be part of a wordlist, that may or may not
be in the search order.

>There could be a penalty to doing it this way, but I don't see that
>it's hard to impossible.
>

<ALTERNATIVE FOR NESTED COMPILATION SKIPPED>


>
>Have I misunderstood what you're trying to do?

No. Maybe I'm exaggerating, but I sure think CO is useful.
Combine the two examples, i.e. use locals in the context of
nested compilation for error recovery. Things get messier.
Your code is much longer. In the locals example CO saves
half a dozen colon definitions.

Groetjes Albert

Albert van der Horst

unread,
Apr 10, 2004, 3:40:11 PM4/10/04
to
In article <2004Apr1...@a0.complang.tuwien.ac.at>,

Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
>>>What I don't like about LATER and >EXEC is that they fail in the
>>>presence of exceptions:
>>>
>>>: test2 setup-scr setup-win abort ; ok
>>>test2
>>>
>>>prints:
>>>
>>>opening screen
>>>opening window
>>>
>>>*the terminal*:9: Aborted
>>>....
>>
>>As far as I can see, this is exactly the behaviour I want.
>>What do you want?
>
>I want the setup to be reverted when test2 is left. I.e.:
>
>opening screen
>opening window
>closing window
>closing screen
>
>*the terminal*:9: Aborted
>
>In the present example, you may not see the problem of not doing the
>cleanup on throwing. But consider cases like:

Of course I see a problem there. But that is no different from
other situations with THROW , say after READ-FILE THROW you are
certainly notified of a problem, but the file is not closed.

One knows that situation and is aware that it must be handled.
Changing that, makes it unexpected, hence worse.

jonah thomas

unread,
Apr 12, 2004, 1:33:41 PM4/12/04
to
Albert van der Horst wrote:
> jonah thomas <j2th...@cavtel.net> wrote:

>>: : 0 ; \ have : add a flag to its colon-sys

>>: LOCAL \ whatever name you want to use
>> 1+ POSTPONE LOCAL ; IMMEDIATE \ set the flag

>>: ;
>> IF POSTPONE DEALLOCATE-LOCALS THEN
>> POSTPONE ; ; IMMEDIATE

> Of course. That is the alternative I can't think of. Maybe I should


> have said "want not".

Fair enough.

> I just studied a locals implementation (for ciforth) somebody sent to
> me. It was set up such that you could redefine EXIT and he did.
> Then I read up about LOCALS in the ANS manual, and realised that
> DOES> must be redefined too. The CO solution handles this
> automagically. More importantly, you need no longer redefine : .

I didn't bother with DOES> since I've never ever used locals in DOES>
. It doesn't look hard. Anyway, there is an alternative, and I'd
expect it to be more portable and also more complicated.

> Again you overlooked DOES> . Are you sure there isn't more you
> overlook?

No, I'm not sure. I did leave out :NONAME, it's no different. I
expect DOES> is not much different:

: DOES>
IF POSTPONE DEALLOCATE-LOCALS THEN
POSTPONE DOES> 0 ; IMMEDIATE

It has to do both sides.

>>The redefinitions in any case would go into the loadable extension,
>>which would only be used to define words that need locals.

> True. They could even be part of a wordlist, that may or may not
> be in the search order.

So it isn't inflexible and it doesn't change the fundamentals of the
compiler.

>>There could be a penalty to doing it this way, but I don't see that
>>it's hard to impossible.

> <ALTERNATIVE FOR NESTED COMPILATION SKIPPED>

>>Have I misunderstood what you're trying to do?

> No. Maybe I'm exaggerating, but I sure think CO is useful.

It looks very useful to me. It does a whole lot with minimal fuss.

If you aren't careful you might get into trouble with it, particularly
when you've been doing anything else with the return stack. If you're
smart and careful you can avoid those problems and if you're good at
testing you can find them and fix them.

You could reduce those potential problems by for example using a
separate loop stack. You could eliminate them by setting up a dummy
>R stack for programs to use and letting CO manipulate the real
return stack.

In all cases you could have problems porting the code to other
systems, the more you eliminate the traps on your own system the more
often you'll do things that don't port. But if we never used a
convenience that didn't port we'd be stuck with a
least-common-denominator and all it would get us would be easier
porting -- it might make more sense to get it running now and worry
about porting it later.

> Combine the two examples, i.e. use locals in the context of
> nested compilation for error recovery. Things get messier.
> Your code is much longer. In the locals example CO saves
> half a dozen colon definitions.

Agreed. There might be a simpler way to do it along my lines, this
was a first-effort from me, but I strongly doubt there's a way as
simple as CO .

I think there's something worth thinking about here. CO uses a simple
trick to do unusual things at runtime. CO: does more complicated
parsing at compile-time to generate typical, usual code that gets a
very similar run-time effect.

It's two different arrows in the quiver, they don't have exactly the
same effect but there's a lot of overlap. When one doesn't work the
other might.

Anton Ertl

unread,
Apr 15, 2004, 9:22:50 AM4/15/04
to
alb...@spenarnc.xs4all.nl (Albert van der Horst) writes:

Not in throwaway programs, but in many situations I would write the
program such that it closes all the files it opens, even in the case
of an exception. And that's not so hard, either (untested):

: process-file ( addr u fam xt -- )
\ open file, process it with xt ( ... file-id -- ... ), then close it
>r open-file throw r> ( file-id xt )
over >r catch r> ( ball file-id )
close-file throw
throw ;

>One knows that situation and is aware that it must be handled.

No, often one does not know the situation; many of these things that
you have to clean up are implementation details of your code, and you
should not burden the poor caller of your routine (or worse, the poor
user of your system) with them; they should be handled transparently.

And even if you are aware you may not know how to handle it. How do
you close the file without the file-id?

Dr. Bruce R. McFarling

unread,
Apr 16, 2004, 4:30:16 AM4/16/04
to
> What's the common name for this word?
>
> : later 2r> swap 2>r ;
>
> It is used to undo operations in the reverse order they were
> done. Useful for things like allocations, opening files, and so on. An
> example:
>
> : setup-scr ." opening screen" cr later ." closing screen" cr ;
> : setup-win ." opening window" cr later ." closing window" cr ;
> : test setup-scr setup-win ;

Why not do it with a stack -- this is the Quartus stack snippet:

\ stacks 00.3.28 3:09 pm NAB

: stack ( size "name" -- )
create
cells dup here cell+ dup ,
+ , allot ;

: push ( item stack -- )
1 cells over +! @ ! ;

: pop ( stack -- item )
dup @ @ -1 cells rot +! ;

so

: stack-item? ( stack -- flag ) DUP @ < ;

32 stack completions

: complete-actions ( -- )
BEGIN completions stack-item? WHILE
completions pop execute
REPEAT
;

: complete-scr ." closing screen" cr ;

: start-scr ." opening screen" cr ' complete-scr completion push ;

: complete-win ." closing window" cr ;

: start-win ." opening window" cr ' complete-win completions push ;

: test start-scr start-win complete-actions ;


WARNING -- I'll test this later, Quartus is not on my pilot at the
moment (I dumped it trying to get the reader for Baen Books on, but it
was too much of a memory hog so it was all for naught anyway.)

Michael L Gassanenko

unread,
Apr 16, 2004, 2:05:17 PM4/16/04
to
alb...@spenarnc.xs4all.nl (Albert van der Horst) wrote in message news:<HvurI8.MKx...@spenarnc.xs4all.nl>...

> Or
> : >stderr out-file stderr TO out-file-id CO TO out-file ;
>
> \ To get the file-descriptor out of the way Marcel Hendrix would do
> : >stderr out-file >S stderr TO out-file-id CO S> TO out-file ;
>
> \ Tucking under the return address obscures the code somewhat.
> : >stderr
> R> out-file >R >R
> stderr TO out-file-id CO
> R> R> TO out-file >R ;
>

...


> >What I don't like about LATER and >EXEC is that they fail in the
> >presence of exceptions:
> >
> >: test2 setup-scr setup-win abort ; ok
> >test2
> >
> >prints:
> >
> >opening screen
> >opening window
> >
> >*the terminal*:9: Aborted
> >....
>
> As far as I can see, this is exactly the behaviour I want.
> What do you want?
>

Maybe, something like:

\ : ENTER >R ;
: >R' S" R> 2>R" EVALUATE ; IMMEDIATE
: R'> S" 2R> >R" EVALUATE ; IMMEDIATE
: >stderr
out-file >R'
stderr TO out-file-id
R@ ['] ENTER CATCH
R'> TO out-file
THROW
RDROP
;

A working example:

: >R' S" R> 2>R" EVALUATE ; IMMEDIATE
: R'> S" 2R> >R" EVALUATE ; IMMEDIATE
123 VALUE bar
: foo
." init " bar >R'
R@ ['] ENTER CATCH
." windup " R'> TO bar
THROW RDROP ;
: t1 foo 5 TO bar bar . ;
: t2 foo 5 TO bar bar . ABORT ;

t1 bar .
init 5 windup 123 ok[Dec]
t2 bar .
init 5 windup
unhandled exception -1 , aborting
68826104 FORTH ( FORTH ) 68826104 FORTH ( FORTH ) ; 68826104 FORTH ( FORTH )

bar .
123 ok[Dec]

Michael L Gassanenko

unread,
Apr 16, 2004, 2:21:40 PM4/16/04
to
The same thing (see my previous message) with locals
[I'm really sorry, but google updates the newsgroups once
in 8 hours or so, so I cannot post a follow-up to my own message.]

include locals.fth
123 VALUE bar
: foo
R> bar { cont bar-old }
." init "
cont ['] ENTER CATCH
." windup " bar-old TO bar
THROW ;

Albert van der Horst

unread,
Apr 15, 2004, 2:27:04 PM4/15/04
to
<SNIP>

>>
>>Of course I see a problem there. But that is no different from
>>other situations with THROW , say after READ-FILE THROW you are
>>certainly notified of a problem, but the file is not closed.
>
>Not in throwaway programs, but in many situations I would write the
>program such that it closes all the files it opens, even in the case
>of an exception. And that's not so hard, either (untested):
>
>: process-file ( addr u fam xt -- )
>\ open file, process it with xt ( ... file-id -- ... ), then close it
> >r open-file throw r> ( file-id xt )
> over >r catch r> ( ball file-id )
> close-file throw
> throw ;
>
>>One knows that situation and is aware that it must be handled.
>
>No, often one does not know the situation; many of these things that
>you have to clean up are implementation details of your code, and you
>should not burden the poor caller of your routine (or worse, the poor
>user of your system) with them; they should be handled transparently.

You still have not convinced me that there is difference. Either it
is a throw-away program, or one should proceed carefully. That is the
same in both cases.

>And even if you are aware you may not know how to handle it. How do
>you close the file without the file-id?

In my PUT-FILE (errors are thrown) you cannot close the file, because
the file-id has been lost. No different than using CO.

So I restate my point of view. There is no difference. That is a good
thing, because one then can use the some solutions, like you sketch in
your process-file.

>- anton
Groetjes Albert.

--

Anton Ertl

unread,
Apr 18, 2004, 5:12:10 AM4/18/04
to
alb...@spenarnc.xs4all.nl (Albert van der Horst) writes:
>In article <2004Apr1...@a0.complang.tuwien.ac.at>,
>Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
>>Not in throwaway programs, but in many situations I would write the
>>program such that it closes all the files it opens, even in the case
>>of an exception. And that's not so hard, either (untested):
>>
>>: process-file ( addr u fam xt -- )
>>\ open file, process it with xt ( ... file-id -- ... ), then close it
>> >r open-file throw r> ( file-id xt )
>> over >r catch r> ( ball file-id )
>> close-file throw
>> throw ;
>>
>>>One knows that situation and is aware that it must be handled.
>>
>>No, often one does not know the situation; many of these things that
>>you have to clean up are implementation details of your code, and you
>>should not burden the poor caller of your routine (or worse, the poor
>>user of your system) with them; they should be handled transparently.
>
>You still have not convinced me that there is difference.

The difference is in the interface of the word.

a) For a word using CO/LATER, the interface is: "In the ordinary case, it
does ...; it may throw an exception and leave a file open; you can get
the file-id for closing it as follows ...".

b) For a word using PROCESS-FILE, the interface is: "In the ordinary
case, it does ...; it may throw an exception".

A word like b) is much easier to use in a non-throwaway program.

>>And even if you are aware you may not know how to handle it. How do
>>you close the file without the file-id?
>In my PUT-FILE (errors are thrown) you cannot close the file, because
>the file-id has been lost. No different than using CO.

What does your PUT-FILE have to do with what I am writing about?
Apparently it does not follow the design rule I gave above.

[BTW, is not leaving an empty line between cited material and your own
text a new fashion? It certainly makes postings less readable.]

0 new messages