Let me know what you think. I'm adding this to the 4pp repository.
I thought ?DO was supposed to fix the main issues of DO.
Hans Bezemer <the.beez.speaks@gmail.com> writes:
Let me know what you think. I'm adding this to the 4pp repository.
I thought ?DO was supposed to fix the main issues of DO.
Paul Rubin <no.email@nospam.invalid> writes:
I thought ?DO was supposed to fix the main issues of DO.
?DO is an improvement over DO in many cases, but I found the resulting >standard counted-loop variants unsatisfying, and have worked on
improved counted-loop constructs over the last three decades, even as >recently as 2024 <2024Jan28.131537@mips.complang.tuwien.ac.at>.
You can read the "Counted Loops" Section in the manual of Gforth's >development version (currently unavailable on the web ><https://net2o.de/gforth/>, but hopefully online again soon) and think
about why I introduced the various additional words were introduced.
No other Forth system has picked them up, so maybe other Forth systems
do not consider the standard counted loops as unsatisfying as I do, or
maybe they consider the price in additional words to be too high.
- anton
Paul Rubin <no.email@nospam.invalid> writes:
I thought ?DO was supposed to fix the main issues of DO.
?DO is an improvement over DO in many cases, but I found the resulting standard counted-loop variants unsatisfying, and have worked on
improved counted-loop constructs over the last three decades, even as recently as 2024 <2024Jan28.131537@mips.complang.tuwien.ac.at>.
You can read the "Counted Loops" Section in the manual of Gforth's development version (currently unavailable on the web <https://net2o.de/gforth/>, but hopefully online again soon) and think
about why I introduced the various additional words were introduced.
No other Forth system has picked them up, so maybe other Forth systems
do not consider the standard counted loops as unsatisfying as I do, or
maybe they consider the price in additional words to be too high.
- anton
We have painted ourselves in a corner.
I certainly do find DO unsatisfactory. I don't think it can be settled
unless we define the body as a lambda, an anonymous piece of code
that can be executed repeatedly.
The cute trick that DO can be used to handle signed and unsigned indices
at the same time is holding us back.
The idea about +LOOP is also insane. If you have an increment, that must be >defined once and for all.
1 6 2 { IX . } DO[..]
1 3 5 OK
That also fixes decrementing loops:
6 1 -2 { IX . } DO[..]
6 4 2 OK
I certainly do find DO unsatisfactory. I don't think it can be settled
unless we define the body as a lambda, an anonymous piece of code
that can be executed repeatedly.
...
(*) About. I can never remember the proper syntax of descending loops. Not even for my own compiler. It's all very confusing.
albert@spenarnc.xs4all.nl writes:
I certainly do find DO unsatisfactory. I don't think it can be settled
unless we define the body as a lambda, an anonymous piece of code
that can be executed repeatedly.
I now remember doing something like that in my first Forth program. It
got tedious and I decided after a while that I was trying to force-fit >conventions from other languages onto Forth, and that this wasn't proper >Forth style.
albert@spenarnc.xs4all.nl writes:
We have painted ourselves in a corner.
Speak for yourself. I am actually pretty happy with the current set
of Gforth's counted-loop words.
- anton
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that must be defined once and for all.
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:Example:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that
must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can vary
from iteration to iteration.
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that must be >> defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can vary
from iteration to iteration.
--
Krishna
On 3/15/26 09:55, Krishna Myneni wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:Example:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that
must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can
vary from iteration to iteration.
:noname 1000 0 do i . i 1+ +loop ; execute
0 1 3 7 15 31 63 127 255 511 ok
Did you use the proper starting point?
You must start with a denotation, valid in interpreter and compilation
mode that anonymously present an xt. (No environment imported, just
the behaviour)
In article <10p6h8l$163pl$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that must be >>> defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can vary >>from iteration to iteration.
Exactly. That is what wrong with it.
On 15-03-2026 16:01, Krishna Myneni wrote:
On 3/15/26 09:55, Krishna Myneni wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:Example:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that
must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can
vary from iteration to iteration.
:noname 1000 0 do i . i 1+ +loop ; execute
0 1 3 7 15 31 63 127 255 511 ok
No sweat!
: ex 0 999 for i . i 1+ step next ; ok
ex 0 1 3 7 15 31 63 127 255 511 ok
On 3/15/26 13:07, albert@spenarnc.xs4all.nl wrote:
In article <10p6h8l$163pl$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can vary >>>from iteration to iteration.
Exactly. That is what wrong with it.
Just use a constant then. Are you concerned with the present spec's >efficiency?
KM
In article <10p7fni$1hb3l$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/15/26 13:07, albert@spenarnc.xs4all.nl wrote:
In article <10p6h8l$163pl$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can vary >>> >from iteration to iteration.
Exactly. That is what wrong with it.
Just use a constant then. Are you concerned with the present spec's
efficiency?
I interpret efficiency as speed of the compiled code.
I don't care about that. I want transparent code, that
-- if and when you choose to optimise -- does not hinder
optimisation.
My philosophy is, that you only optimise procedures that needs
to be fast, not as a global flag for a compiler, or a
permanent burden that has to be present (and errorfree)
for the compiler.
Groetjes Albert
On 3/15/26 13:11, Hans Bezemer wrote:
On 15-03-2026 16:01, Krishna Myneni wrote:
On 3/15/26 09:55, Krishna Myneni wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:Example:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that >>>>> must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can
vary from iteration to iteration.
:noname 1000 0 do i . i 1+ +loop ; execute
0 1 3 7 15 31 63 127 255 511 ok
No sweat!
: ex 0 999 for i . i 1+ step next ; ok
ex 0 1 3 7 15 31 63 127 255 511 ok
What does the following do when you substitute FOR ... STEP NEXT for DO
... +LOOP ?
-1 1 rshift constant MAX-INT
MAX-INT DUP 2/ + CONSTANT LIM
MAX-INT 4 / CONSTANT INCR
: ex LIM 0 DO I . CR INCR +LOOP ;
Per my understanding of the standard for +LOOP on 2's complement 64-bit systems, it should output the following.
0
2305843009213693951
4611686018427387902
6917529027641081853
9223372036854775804
-6917529027641081861
-4611686018427387910
ok
--
Krishna
P.S. I had to fix the behavior of +LOOP in kForth-64 recently, to pass
Gerry Jackson's coreplustest suite of tests for +LOOP.
In article <10p7fni$1hb3l$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/15/26 13:07, albert@spenarnc.xs4all.nl wrote:
In article <10p6h8l$163pl$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can vary >>> >from iteration to iteration.
Exactly. That is what wrong with it.
Just use a constant then. Are you concerned with the present spec's
efficiency?
I interpret efficiency as speed of the compiled code.
I don't care about that. I want transparent code, that
-- if and when you choose to optimise -- does not hinder
optimisation.
My philosophy is, that you only optimise procedures that needs
to be fast, not as a global flag for a compiler, or a
permanent burden that has to be present (and errorfree)
for the compiler.
KM
Groetjes Albert
On 3/16/26 06:26, albert@spenarnc.xs4all.nl wrote:
In article <10p7fni$1hb3l$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/15/26 13:07, albert@spenarnc.xs4all.nl wrote:
In article <10p6h8l$163pl$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment,
that must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can
vary
from iteration to iteration.
Exactly. That is what wrong with it.
Just use a constant then. Are you concerned with the present spec's
efficiency?
I interpret efficiency as speed of the compiled code.
I don't care about that. I want transparent code, that
-- if and when you choose to optimise -- does not hinder
optimisation.
My philosophy is, that you only optimise procedures that needs
to be fast, not as a global flag for a compiler, or a
permanent burden that has to be present (and errorfree)
for the compiler.
+LOOP is transparent once you view it properly as stepping through the unsigned numbers and wrapping around, either in positive increments
which increase the unsigned number or in negative increments which
decrease the unsigned number e.g.
---
MAX-UINT
:
:
MIN-INT
MAX-INT
:
:
0
---
--
KM
Groetjes Albert
In article <10p6h8l$163pl$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that must be >>> defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can vary >>from iteration to iteration.
Exactly. That is what wrong with it.
On 16-03-2026 01:36, Krishna Myneni wrote:
On 3/15/26 13:11, Hans Bezemer wrote:
On 15-03-2026 16:01, Krishna Myneni wrote:
On 3/15/26 09:55, Krishna Myneni wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:Example:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment,
that must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a >>>>> fixed step. It uses whatever is on the stack, so the increment can
vary from iteration to iteration.
:noname 1000 0 do i . i 1+ +loop ; execute
0 1 3 7 15 31 63 127 255 511 ok
No sweat!
: ex 0 999 for i . i 1+ step next ; ok
ex 0 1 3 7 15 31 63 127 255 511 ok
What does the following do when you substitute FOR ... STEP NEXT for
DO ... +LOOP ?
-1 1 rshift constant MAX-INT
MAX-INT DUP 2/ + CONSTANT LIM
MAX-INT 4 / CONSTANT INCR
: ex LIM 0 DO I . CR INCR +LOOP ;
Per my understanding of the standard for +LOOP on 2's complement 64-
bit systems, it should output the following.
0
2305843009213693951
4611686018427387902
6917529027641081853
9223372036854775804
-6917529027641081861
-4611686018427387910
ok
--
Krishna
P.S. I had to fix the behavior of +LOOP in kForth-64 recently, to pass
Gerry Jackson's coreplustest suite of tests for +LOOP.
for compiling
postpone 1+ postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone < postpone while ; immediate
ok
: -for compiling
postpone 1- postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone > postpone while ; immediate ok
: step postpone r> postpone + postpone r> postpone repeat ; immediate ok : next postpone rdrop postpone rdrop ; immediate
ok
-1 1 rshift constant MAX-INT ok
ok
MAX-INT DUP 2/ + CONSTANT LIM ok
MAX-INT 4 / CONSTANT INCR ok
ok
: ex 0 LIM 1- FOR I . CR INCR STEP NEXT ; ok
ex ok
It does what it is supposed to do: quit the loop, since
-4611686018427387906 is smaller than 0. But what exactly do you want to prove here? That it does a signed compare? Doesn't that tell you exactly what one has to fix here - if you INSIST on having an unsigned
comparison (which, IMHO was one of the worst decisions Forth-83 EVER
made). I mean - how often have you used such a loop in general programming?
: for compiling
postpone 1+ postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone < postpone while ; immediate
ok
: ufor compiling
postpone 1+ postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone u< postpone while ; immediate ok
ok
: -for compiling
postpone 1- postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone > postpone while ; immediate
ok
: step postpone r> postpone + postpone r> postpone repeat ; immediate
: next postpone rdrop postpone rdrop ; immediate
ok
ok
-1 1 rshift constant MAX-INT
ok
MAX-INT DUP 2/ + CONSTANT LIM
MAX-INT 4 / CONSTANT INCR
ok
: ex 0 LIM 1- UFOR I . CR INCR STEP NEXT ;
ok
ex 0
2305843009213693951
4611686018427387902
6917529027641081853
9223372036854775804
-6917529027641081861
-4611686018427387910
ok
QED. If you can have a -FOR, why not a UFOR? Duh!
On 3/16/26 08:28, Hans Bezemer wrote:
On 16-03-2026 01:36, Krishna Myneni wrote:I don't need six or seven variants of DO ... +LOOP. IMO, it's cleaner
On 3/15/26 13:11, Hans Bezemer wrote:
On 15-03-2026 16:01, Krishna Myneni wrote:
On 3/15/26 09:55, Krishna Myneni wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:Example:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment,
that must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use >>>>>> a fixed step. It uses whatever is on the stack, so the increment
can vary from iteration to iteration.
:noname 1000 0 do i . i 1+ +loop ; execute
0 1 3 7 15 31 63 127 255 511 ok
No sweat!
: ex 0 999 for i . i 1+ step next ; ok
ex 0 1 3 7 15 31 63 127 255 511 ok
What does the following do when you substitute FOR ... STEP NEXT for
DO ... +LOOP ?
-1 1 rshift constant MAX-INT
MAX-INT DUP 2/ + CONSTANT LIM
MAX-INT 4 / CONSTANT INCR
: ex LIM 0 DO I . CR INCR +LOOP ;
Per my understanding of the standard for +LOOP on 2's complement 64-
bit systems, it should output the following.
0
2305843009213693951
4611686018427387902
6917529027641081853
9223372036854775804
-6917529027641081861
-4611686018427387910
ok
--
Krishna
P.S. I had to fix the behavior of +LOOP in kForth-64 recently, to
pass Gerry Jackson's coreplustest suite of tests for +LOOP.
for compiling
postpone 1+ postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone < postpone while ; immediate
ok
: -for compiling
postpone 1- postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone > postpone while ; immediate ok
: step postpone r> postpone + postpone r> postpone repeat ;
immediate ok
: next postpone rdrop postpone rdrop ; immediate
ok
-1 1 rshift constant MAX-INT ok
ok
MAX-INT DUP 2/ + CONSTANT LIM ok
MAX-INT 4 / CONSTANT INCR ok
ok
: ex 0 LIM 1- FOR I . CR INCR STEP NEXT ; ok
ex ok
It does what it is supposed to do: quit the loop, since
-4611686018427387906 is smaller than 0. But what exactly do you want
to prove here? That it does a signed compare? Doesn't that tell you
exactly what one has to fix here - if you INSIST on having an unsigned
comparison (which, IMHO was one of the worst decisions Forth-83 EVER
made). I mean - how often have you used such a loop in general
programming?
: for compiling
postpone 1+ postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone < postpone while ; immediate
ok
: ufor compiling
postpone 1+ postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone u< postpone while ; immediate ok >> ok
: -for compiling
postpone 1- postpone begin postpone over postpone over compiling
postpone >r postpone >r postpone > postpone while ; immediate
ok
: step postpone r> postpone + postpone r> postpone repeat ; immediate
: next postpone rdrop postpone rdrop ; immediate
ok
ok
-1 1 rshift constant MAX-INT
ok
MAX-INT DUP 2/ + CONSTANT LIM
MAX-INT 4 / CONSTANT INCR
ok
: ex 0 LIM 1- UFOR I . CR INCR STEP NEXT ;
ok
ex 0
2305843009213693951
4611686018427387902
6917529027641081853
9223372036854775804
-6917529027641081861
-4611686018427387910
ok
QED. If you can have a -FOR, why not a UFOR? Duh!
just to understand DO ... +LOOP and use it correctly.
--
KM
I can understand the need for an unsigned DO..LOOP in the 16-bit era,
but there is no need for that in the 32-bit era.
One of the huge errors of Forth-83 standard was they caved in to
pressure and made DO..LOOP unsigned. Gee folks, can't you really bake an >unsigned BEGIN..REPEAT? Really?
But I'll never defend a lousy construct - my own or someone elses - for
any reason. At best, I'll excuse myself by saying I'm too lazy too fix it.
Hans Bezemer
On 15/03/2026 18:07, albert@spenarnc.xs4all.nl wrote:
In article <10p6h8l$163pl$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
On 3/14/26 09:13, albert@spenarnc.xs4all.nl wrote:
In article <2026Mar14.115416@mips.complang.tuwien.ac.at>,
The idea about +LOOP is also insane. If you have an increment, that must be
defined once and for all.
Maybe I misunderstand what you are saying, but +LOOP does not use a
fixed step. It uses whatever is on the stack, so the increment can vary >>>from iteration to iteration.
Exactly. That is what wrong with it.
Wrong, if varying the increment does what you require it's right.
A trivial example
: fib 1 swap 0 do i . i swap +loop drop ; cr 1000 fib
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 ok
--
Gerry
I don't need six or seven variants of DO ... +LOOP. IMO, it's cleaner
just to understand DO ... +LOOP and use it correctly.
KM
In article <10p991u$23uka$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
<SNIP>
I don't need six or seven variants of DO ... +LOOP. IMO, it's cleaner
just to understand DO ... +LOOP and use it correctly.
You trade memory burden for insight. If you can do it, it
is advantageous. The formule for cos(a+b) is insane.
It you understand exp(i(a+b)) it falls in place.
I don't have a mensa level iq. If you want other people to
understand your programs, that is maybe not the right attitude.
Also if you are pushing eighty, (as I am), you risk that you no
longer understand your own programs.
On 3/16/26 2:25 PM, albert@spenarnc.xs4all.nl wrote:
In article <10p991u$23uka$1@dont-email.me>,
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
<SNIP>
I don't need six or seven variants of DO ... +LOOP. IMO, it's cleaner
just to understand DO ... +LOOP and use it correctly.
You trade memory burden for insight. If you can do it, it
is advantageous. The formule for cos(a+b) is insane.
It you understand exp(i(a+b)) it falls in place.
I don't have a mensa level iq. If you want other people to
understand your programs, that is maybe not the right attitude.
Also if you are pushing eighty, (as I am), you risk that you no
longer understand your own programs.
Admittedly it took me the better part of two days to figure out the
logic to make +LOOP pass the coreplustest tests. However, most of the difficulty was getting the conceptual picture correct in my head for
what it is intended to do. After that the coding wasn't that hard.
I don't have anything against someone coding a special variant or two of
the stepped loops for signed integers, with different loop iteration behavior. But, one should be careful about the following
1) they are not replacements for DO ... +LOOP
2) they can also be misused
3) not to proliferate so many types of loops that it becomes a memory
burden
--
KM
| Sysop: | DaiTengu |
|---|---|
| Location: | Appleton, WI |
| Users: | 1,105 |
| Nodes: | 10 (0 / 10) |
| Uptime: | 492369:17:40 |
| Calls: | 14,160 |
| Calls today: | 2 |
| Files: | 186,285 |
| D/L today: |
2,035 files (639M bytes) |
| Messages: | 2,503,450 |