Bezemer had the idea to borrow a loop construct from other languages.
Why not borrow from the best: Algol68.
One could implement anything in Forth, not?
It looks like
for .. from .. by .. to .. while .. do .. od
The first 5 are optional.
while .. do .. od
is actually
BEGIN WHILE REPEAT
and
do .. od
is actually
BEGIN AGAIN
while .. do od
(empty do .. od)
is actually
REPEAT ... NOT UNTIL
FOR could be followed by a name, declaring a LOCAL index.
Or the convention that I is the index could be kept.
7 key words replacing BEGIN REPEAT WHILE UNTIL DO LOOP ?DO
that does everything.
It ends the craving for extensions, because it is inherently complete.
Not a bad deal.
Default for from : 1
Default for by : 1
Default for to : infinity
Default for while : TRUE
Groetjes Albert
On 15-03-2026 12:20, albert@spenarnc.xs4all.nl wrote:
Bezemer had the idea to borrow a loop construct from other languages.
Why not borrow from the best: Algol68.
One could implement anything in Forth, not?
It looks like
for .. from .. by .. to .. while .. do .. od
The first 5 are optional.
while .. do .. od
is actually
BEGIN WHILE REPEAT
and
do .. od
is actually
BEGIN AGAIN
while .. do od
(empty do .. od)
is actually
REPEAT ... NOT UNTIL
FOR could be followed by a name, declaring a LOCAL index.
Or the convention that I is the index could be kept.
7 key words replacing BEGIN REPEAT WHILE UNTIL DO LOOP ?DO
that does everything.
It ends the craving for extensions, because it is inherently complete.
Not a bad deal.
Default for from : 1
Default for by : 1
Default for to : infinity
Default for while : TRUE
Groetjes Albert
If you'd added code, it would have been a lot more convincing ;-)
Everybody has beautiful ideas. Few have code.
Hans Bezemer
Bezemer had the idea to borrow a loop construct from other languages.
Why not borrow from the best: Algol68.
One could implement anything in Forth, not?
It looks like
for .. from .. by .. to .. while .. do .. od
The first 5 are optional.
while .. do .. od
is actually
BEGIN WHILE REPEAT
and
do .. od
is actually
BEGIN AGAIN
while .. do od
(empty do .. od)
is actually
REPEAT ... NOT UNTIL
FOR could be followed by a name, declaring a LOCAL index.
Or the convention that I is the index could be kept.
7 key words replacing BEGIN REPEAT WHILE UNTIL DO LOOP ?DO
that does everything.
It ends the craving for extensions, because it is inherently complete.
albert@spenarnc.xs4all.nl wrote:
Bezemer had the idea to borrow a loop construct from other languages.
Why not borrow from the best: Algol68.
One could implement anything in Forth, not?
It looks like
for .. from .. by .. to .. while .. do .. od
The first 5 are optional.
while .. do .. od
is actually
BEGIN WHILE REPEAT
and
do .. od
is actually
BEGIN AGAIN
while .. do od
(empty do .. od)
is actually
REPEAT ... NOT UNTIL
FOR could be followed by a name, declaring a LOCAL index.
Or the convention that I is the index could be kept.
7 key words replacing BEGIN REPEAT WHILE UNTIL DO LOOP ?DO
that does everything.
It ends the craving for extensions, because it is inherently complete.
I doubt completeness, at least in version you describe. Consider
the following non-forth loop header:
for i in li for j in 0..(n - 1) repeat
The first for clause means iteration over a list, second is usual
iteration over integers. In construct above you can have
arbitrarly many 'for' and 'while' clauses and also 'such that'
cluse. 'for' clause work in parallel, 'while' exits the loop
when false, 'such that' skips current interation when false.
That is pretty general, yet people proposed extentions...
The syntax like above is easy to translate to stack machine with
locals, but without locals is problematic.
Waldek Hebisch
In article <10p74h0$27v6e$2@paganini.bofh.team>,
Waldek Hebisch <antispam@fricas.org> wrote:
albert@spenarnc.xs4all.nl wrote:
Bezemer had the idea to borrow a loop construct from other languages.
Why not borrow from the best: Algol68.
One could implement anything in Forth, not?
It looks like
for .. from .. by .. to .. while .. do .. od
The first 5 are optional.
while .. do .. od
is actually
BEGIN WHILE REPEAT
and
do .. od
is actually
BEGIN AGAIN
while .. do od
(empty do .. od)
is actually
REPEAT ... NOT UNTIL
FOR could be followed by a name, declaring a LOCAL index.
Or the convention that I is the index could be kept.
7 key words replacing BEGIN REPEAT WHILE UNTIL DO LOOP ?DO
that does everything.
It ends the craving for extensions, because it is inherently complete.
I doubt completeness, at least in version you describe. Consider
the following non-forth loop header:
for i in li for j in 0..(n - 1) repeat
The first for clause means iteration over a list, second is usual
iteration over integers. In construct above you can have
arbitrarly many 'for' and 'while' clauses and also 'such that'
cluse. 'for' clause work in parallel, 'while' exits the loop
when false, 'such that' skips current interation when false.
That is pretty general, yet people proposed extentions...
The syntax like above is easy to translate to stack machine with
locals, but without locals is problematic.
Completeness is as far as it goes. You enter the realm of the
map functionality of lisp. Proposed extensions to looping in Forth
do not go that far.
Note that lists and enumeration denotation are an essential
extensions. I restricted my self to what can be done with
loop parameters on the return stack and BRANCH / 0BRANCH .
albert@spenarnc.xs4all.nl wrote:
Bezemer had the idea to borrow a loop construct from other languages.
Why not borrow from the best: Algol68.
One could implement anything in Forth, not?
It looks like
for .. from .. by .. to .. while .. do .. od
The first 5 are optional.
while .. do .. od
is actually
BEGIN WHILE REPEAT
and
do .. od
is actually
BEGIN AGAIN
while .. do od
(empty do .. od)
is actually
REPEAT ... NOT UNTIL
FOR could be followed by a name, declaring a LOCAL index.
Or the convention that I is the index could be kept.
7 key words replacing BEGIN REPEAT WHILE UNTIL DO LOOP ?DO
that does everything.
It ends the craving for extensions, because it is inherently complete.
I doubt completeness, at least in version you describe. Consider
the following non-forth loop header:
for i in li for j in 0..(n - 1) repeat
The first for clause means iteration over a list, second is usual
iteration over integers. In construct above you can have
arbitrarly many 'for' and 'while' clauses and also 'such that'
cluse. 'for' clause work in parallel, 'while' exits the loop
when false, 'such that' skips current interation when false.
That is pretty general, yet people proposed extentions...
The syntax like above is easy to translate to stack machine with
locals, but without locals is problematic.
Well, you already got FOR. This is FOREACH:
: foreach ( 'f addr count -- )
cells bounds do
I @ over execute
loop drop ;
...
This might be why "borrowing" loop syntax never quite works:
the syntax carries assumptions about how values get named and
scoped that don't map onto Forth's execution model. You can
implement the syntax, but you end up fighting the stack.
I agree with this. Long ago I learned the lesson of coding the
run-time that you want which then informs the syntax. It's the
run-time and its efficiency that's important. It's why I consider
DO LOOP (particularly '83) so clever. Bang for buck it remains
hard to beat.
...
What made '83 DO LOOP particularly good in this regard? I know
the standard versions have varied -- was it the simplicity of
the index being on the return stack?
Index were always on the return stack. Previous DO LOOPs had issues
relating to LEAVE and number range. 83' LOOP was faster albeit with
a more costly initialization. There was a write-up in Forth Dimensions
by Robert Smith:
https://www.forth.org/fd/FD-V04N3.pdf page 24
...
The LEAVE issue is one I hadn't considered. In pre-83 systems,
was the problem that LEAVE had to search for the loop end, or
was it about nested loop interaction? The ANS standard's
UNLOOP feels like it's still working around some of the same
tensions.
On 20/03/2026 12:09 am, Lev wrote:
...
The LEAVE issue is one I hadn't considered. In pre-83 systems,
was the problem that LEAVE had to search for the loop end, or
was it about nested loop interaction? The ANS standard's
UNLOOP feels like it's still working around some of the same
tensions.
79-LEAVE simply set the index to the limit. The programmer had
to ensure a path to LOOP for exit to occur. In contrast 83-LEAVE
knows where to jump and can exit immediately.
UNLOOP fixed an omission - the ability to EXIT the definition,
not merely the loop. Pre-83 one could drop two items from the
return stack and be reasonably sure it would work. By 83 odds
were that it wouldn't.
Now, remember that 4tH not only saves a location, but also a
reference. E.g. the location of the "IF" is stored along with
a reference "I am an IF!"
Imagine what the control stack looks like when a "THEN" is
encountered:
DO + location
IF + location
LEAVE + location
I cannot resolve the "IF" because "LEAVE" is TOCS.
Of course, decreasing loops are in no way ANS-compliant
79-LEAVE simply set the index to the limit. The programmer had
to ensure a path to LOOP for exit to occur. In contrast 83-LEAVE
knows where to jump and can exit immediately.
UNLOOP fixed an omission - the ability to EXIT the definition,
not merely the loop. Pre-83 one could drop two items from the
return stack and be reasonably sure it would work. By 83 odds
were that it wouldn't.
79-LEAVE simply set the index to the limit. The programmer had
to ensure a path to LOOP for exit to occur. In contrast 83-LEAVE
knows where to jump and can exit immediately.
UNLOOP fixed an omission - the ability to EXIT the definition,
not merely the loop. Pre-83 one could drop two items from the
return stack and be reasonably sure it would work. By 83 odds
were that it wouldn't.
On 19-03-2026 17:18, dxf wrote:
On 20/03/2026 12:09 am, Lev wrote:
...
The LEAVE issue is one I hadn't considered. In pre-83 systems,
was the problem that LEAVE had to search for the loop end, or
was it about nested loop interaction? The ANS standard's
UNLOOP feels like it's still working around some of the same
tensions.
79-LEAVE simply set the index to the limit. The programmer had
to ensure a path to LOOP for exit to occur. In contrast 83-LEAVE
knows where to jump and can exit immediately.
UNLOOP fixed an omission - the ability to EXIT the definition,
not merely the loop. Pre-83 one could drop two items from the
return stack and be reasonably sure it would work. By 83 odds
were that it wouldn't.
Well - there is a price to be paid for all that fancy stuff. 4tH largely copies Forth-79. "LEAVE" is equivalent to "RDROP R@ >R". "UNLOOP" is equivalent to "RDROP RDROP".
The point is - "LEAVE" isn't like "WHILE". "LEAVE" is *always* buried in one or more "IF" constructs.
...
| Sysop: | DaiTengu |
|---|---|
| Location: | Appleton, WI |
| Users: | 1,102 |
| Nodes: | 10 (0 / 10) |
| Uptime: | 492328:10:46 |
| Calls: | 14,132 |
| Calls today: | 2 |
| Files: | 186,278 |
| D/L today: |
3,501 files (1,225M bytes) |
| Messages: | 2,501,393 |