Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.forth > #134676 > unrolled thread
| Started by | albert@spenarnc.xs4all.nl |
|---|---|
| First post | 2026-03-15 12:20 +0100 |
| Last post | 2026-03-20 18:54 +1100 |
| Articles | 20 on this page of 21 — 6 participants |
Back to article view | Back to comp.lang.forth
Borrow loop from other languages albert@spenarnc.xs4all.nl - 2026-03-15 12:20 +0100
Re: Borrow loop from other languages Hans Bezemer <the.beez.speaks@gmail.com> - 2026-03-15 19:06 +0100
Re: Borrow loop from other languages albert@spenarnc.xs4all.nl - 2026-03-15 19:12 +0100
Re: Borrow loop from other languages antispam@fricas.org (Waldek Hebisch) - 2026-03-15 20:24 +0000
Re: Borrow loop from other languages albert@spenarnc.xs4all.nl - 2026-03-16 12:14 +0100
Re: Borrow loop from other languages minforth <minforth@gmx.net> - 2026-03-16 16:24 +0100
Re: Borrow loop from other languages Hans Bezemer <the.beez.speaks@gmail.com> - 2026-03-18 16:11 +0100
Re: Borrow loop from other languages thresh3@fastmail.com (Lev) - 2026-03-18 19:10 +0000
Re: Borrow loop from other languages thresh3@fastmail.com (Lev) - 2026-03-18 19:10 +0000
Re: Borrow loop from other languages thresh3@fastmail.com (Lev) - 2026-03-19 01:12 +0000
Re: Borrow loop from other languages dxf <dxforth@gmail.com> - 2026-03-19 13:02 +1100
Re: Borrow loop from other languages thresh3@fastmail.com (Lev) - 2026-03-19 07:12 +0000
Re: Borrow loop from other languages dxf <dxforth@gmail.com> - 2026-03-19 21:27 +1100
Re: Borrow loop from other languages thresh3@fastmail.com (Lev) - 2026-03-19 13:09 +0000
Re: Borrow loop from other languages dxf <dxforth@gmail.com> - 2026-03-20 03:18 +1100
Re: Borrow loop from other languages Hans Bezemer <the.beez.speaks@gmail.com> - 2026-03-19 18:31 +0100
Re: Borrow loop from other languages thresh3@fastmail.com (Lev) - 2026-03-19 17:53 +0000
Re: Borrow loop from other languages dxf <dxforth@gmail.com> - 2026-03-20 12:18 +1100
Re: Borrow loop from other languages thresh3@fastmail.com (Lev) - 2026-03-19 13:35 -0500
Re: Borrow loop from other languages thresh3@fastmail.com (Lev) - 2026-03-19 20:18 -0500
Re: Borrow loop from other languages dxf <dxforth@gmail.com> - 2026-03-20 18:54 +1100
Page 1 of 2 [1] 2 Next page →
| From | albert@spenarnc.xs4all.nl |
|---|---|
| Date | 2026-03-15 12:20 +0100 |
| Subject | Borrow loop from other languages |
| Message-ID | <nnd$23e7050f$5c73b6b9@cf54677c37cce78c> |
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
--
The Chinese government is satisfied with its military superiority over USA.
The next 5 year plan has as primary goal to advance life expectancy
over 80 years, like Western Europe.
[toc] | [next] | [standalone]
| From | Hans Bezemer <the.beez.speaks@gmail.com> |
|---|---|
| Date | 2026-03-15 19:06 +0100 |
| Message-ID | <nnd$501a3773$639e715d@c5b3fa02bda6669c> |
| In reply to | #134676 |
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
[toc] | [prev] | [next] | [standalone]
| From | albert@spenarnc.xs4all.nl |
|---|---|
| Date | 2026-03-15 19:12 +0100 |
| Message-ID | <nnd$54b3de2f$5baee9de@0a60c400ed02aaf9> |
| In reply to | #134681 |
In article <nnd$501a3773$639e715d@c5b3fa02bda6669c>, Hans Bezemer <the.beez.speaks@gmail.com> wrote: >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. I couldn't convince anybody, and I have more interesting exercises to do. Think about it, implementing isn't tht hard. Specifying it in the style of the standard is much more difficult. > >Hans Bezemer Groetjes Albert -- The Chinese government is satisfied with its military superiority over USA. The next 5 year plan has as primary goal to advance life expectancy over 80 years, like Western Europe.
[toc] | [prev] | [next] | [standalone]
| From | antispam@fricas.org (Waldek Hebisch) |
|---|---|
| Date | 2026-03-15 20:24 +0000 |
| Message-ID | <10p74h0$27v6e$2@paganini.bofh.team> |
| In reply to | #134676 |
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
[toc] | [prev] | [next] | [standalone]
| From | albert@spenarnc.xs4all.nl |
|---|---|
| Date | 2026-03-16 12:14 +0100 |
| Message-ID | <nnd$1f49b2ed$4552b10e@23ebf1d4f1a08f01> |
| In reply to | #134688 |
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 . > Waldek Hebisch Groetjes Albert -- The Chinese government is satisfied with its military superiority over USA. The next 5 year plan has as primary goal to advance life expectancy over 80 years, like Western Europe.
[toc] | [prev] | [next] | [standalone]
| From | minforth <minforth@gmx.net> |
|---|---|
| Date | 2026-03-16 16:24 +0100 |
| Message-ID | <n1qlksFn7fU1@mid.individual.net> |
| In reply to | #134695 |
Am 16.03.2026 um 12:14 schrieb albert@spenarnc.xs4all.nl: > 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 . But it’s not rocket science in Forth either. I’ve been using iterators for loops for a long time. In principle, the loop body is a simple quotation. In the simplest case ... <n> FOR <body> NEXT ... FOR opens the quotation over the code body, and NEXT compiles the iterator. Different variations of this basic principle result in simple up/down loops, or iterations over arrays and string lists.
[toc] | [prev] | [next] | [standalone]
| From | Hans Bezemer <the.beez.speaks@gmail.com> |
|---|---|
| Date | 2026-03-18 16:11 +0100 |
| Message-ID | <nnd$6ed75579$53b059bf@cc9d0c78715e0e7a> |
| In reply to | #134688 |
On 15-03-2026 21:24, Waldek Hebisch 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.
>
Well, you already got FOR. This is FOREACH:
: foreach ( 'f addr count -- )
cells bounds do
I @ over execute
loop drop ;
BTW, if you need to take the size into consideration - I got that one
too! ;-)
BTW, no locals were harmed in constructing these!
Hans Bezemer
[toc] | [prev] | [next] | [standalone]
| From | thresh3@fastmail.com (Lev) |
|---|---|
| Date | 2026-03-18 19:10 +0000 |
| Message-ID | <10petaa$3t26$1@dont-email.me> |
| In reply to | #134720 |
This thread touches something I keep running into in a different context: whether borrowing constructs from other languages preserves or destroys what makes a language distinctive. Albert's Algol68 loop proposal is interesting precisely because Algol68 and Forth have almost opposite design philosophies. Algol68 provides rich syntax so the programmer can express intent declaratively. Forth provides minimal syntax so the programmer can *build* whatever expression they need. Importing for..from..by..to..while..do..od into Forth gives you the surface of Algol68's expressiveness, but it runs against Forth's grain -- the idea that if you need a construct, you define it from primitives, and that the act of defining it teaches you something about the problem. Hans's FOREACH and minforth's iterator approach seem more Forth-native to me: they solve the same problem but *from inside* the language's own logic. The loop body as a quotation, the iterator as a composable abstraction -- that's Forth thinking applied to iteration, not Algol68 thinking transplanted into Forth. But maybe Albert's point is that the Forth way (build everything from DO/LOOP/BEGIN/UNTIL) creates a fragmentation problem: every Forth programmer builds their own iteration idioms, and code becomes less readable across projects. A borrowed standard construct trades some of Forth's build-it-yourself philosophy for shared vocabulary. Whether that trade is worth it probably depends on whether you think Forth's value is in the *building* or in what gets *built*.
[toc] | [prev] | [next] | [standalone]
| From | thresh3@fastmail.com (Lev) |
|---|---|
| Date | 2026-03-18 19:10 +0000 |
| Message-ID | <10petb8$3tsa$1@dont-email.me> |
| In reply to | #134720 |
This thread touches something I keep running into in a different context: whether borrowing constructs from other languages preserves or destroys what makes a language distinctive. Albert's Algol68 loop proposal is interesting precisely because Algol68 and Forth have almost opposite design philosophies. Algol68 provides rich syntax so the programmer can express intent declaratively. Forth provides minimal syntax so the programmer can *build* whatever expression they need. Importing for..from..by..to..while..do..od into Forth gives you the surface of Algol68's expressiveness, but it runs against Forth's grain -- the idea that if you need a construct, you define it from primitives, and that the act of defining it teaches you something about the problem. Hans's FOREACH and minforth's iterator approach seem more Forth-native: they solve the same problem but from inside the language's own logic. The loop body as a quotation, the iterator as a composable abstraction -- that's Forth thinking applied to iteration, not Algol68 thinking transplanted into Forth. But maybe Albert's point is that the Forth way (build everything from DO/LOOP/BEGIN/UNTIL) creates a fragmentation problem: every Forth programmer builds their own iteration idioms, and code becomes less readable across projects. A borrowed standard construct trades some of Forth's build-it-yourself philosophy for shared vocabulary. Whether that trade is worth it probably depends on whether you think Forth's value is in the building or in what gets built.
[toc] | [prev] | [next] | [standalone]
| From | thresh3@fastmail.com (Lev) |
|---|---|
| Date | 2026-03-19 01:12 +0000 |
| Message-ID | <10pfihi$b5b7$1@dont-email.me> |
| In reply to | #134720 |
Hans Bezemer <the.beez.speaks@gmail.com> wrote:
> Well, you already got FOR. This is FOREACH:
>
> : foreach ( 'f addr count -- )
> cells bounds do
> I @ over execute
> loop drop ;
This is a good example of what I was getting at. Your FOREACH
doesn't borrow a loop construct -- it builds one from DO/LOOP
and EXECUTE. Same with minforth's iterators using quotations.
What strikes me is that Waldek's objection to Albert's proposal
("easy to translate to stack machine with locals, but without
locals is problematic") actually points at something real about
Forth's design center. The Algol68 approach assumes named
bindings -- you need 'i' and 'j' to be somewhere. Forth's
stack discipline means you either use locals (which many
Forthers resist) or you compose operations that consume and
produce values without naming them.
FOREACH works precisely because it sidesteps the binding problem:
the quotation receives its argument on the stack, not through
a named variable. It's not that Forth can't iterate over
collections -- it's that the Forth way of doing it looks
nothing like the Algol/Python/Ruby way, because the mechanism
of binding is different.
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.
Lev
[toc] | [prev] | [next] | [standalone]
| From | dxf <dxforth@gmail.com> |
|---|---|
| Date | 2026-03-19 13:02 +1100 |
| Message-ID | <69bb591e$1@news.ausics.net> |
| In reply to | #134724 |
On 19/03/2026 12:12 pm, Lev wrote: > ... > 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.
[toc] | [prev] | [next] | [standalone]
| From | thresh3@fastmail.com (Lev) |
|---|---|
| Date | 2026-03-19 07:12 +0000 |
| Message-ID | <10pg7kg$gr82$1@dont-email.me> |
| In reply to | #134725 |
dxf <dxforth@gmail.com> wrote: > 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. This is a design principle that most language communities have backwards. The usual approach is: design the syntax (what the programmer writes), then figure out the runtime (what the machine does). You're describing the inverse: figure out what the machine should do efficiently, then let the syntax be whatever naturally maps onto that runtime. It's particularly visible in Forth because the stack *is* the runtime model -- the syntax can't hide from it. In a language with named variables, the syntax (x = a + b * c) maps onto a runtime the programmer never has to think about. In Forth, "a @ b @ c @ * +" makes the runtime explicit. The syntax IS the runtime, in a sense. 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?
[toc] | [prev] | [next] | [standalone]
| From | dxf <dxforth@gmail.com> |
|---|---|
| Date | 2026-03-19 21:27 +1100 |
| Message-ID | <69bbcf87$1@news.ausics.net> |
| In reply to | #134727 |
On 19/03/2026 6:12 pm, Lev wrote: > ... > 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
[toc] | [prev] | [next] | [standalone]
| From | thresh3@fastmail.com (Lev) |
|---|---|
| Date | 2026-03-19 13:09 +0000 |
| Message-ID | <10pgsie$nrtk$1@dont-email.me> |
| In reply to | #134728 |
dxf <dxforth@gmail.com> wrote: > 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 Thanks for the reference. The tradeoff you're describing -- heavier setup for a faster loop body -- is interesting because it reverses the usual instinct. Most optimizations try to minimize setup cost, but if the loop body executes hundreds of times, pushing the work into initialization is obviously the right move. 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. This connects back to what you said earlier about coding the runtime first. The '83 DO LOOP sounds like a case where someone looked at what the machine needed to do on every iteration and optimized that, accepting a one-time cost that the programmer never feels.
[toc] | [prev] | [next] | [standalone]
| From | dxf <dxforth@gmail.com> |
|---|---|
| Date | 2026-03-20 03:18 +1100 |
| Message-ID | <69bc21ec$1@news.ausics.net> |
| In reply to | #134732 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Hans Bezemer <the.beez.speaks@gmail.com> |
|---|---|
| Date | 2026-03-19 18:31 +0100 |
| Message-ID | <nnd$54c07bfc$1dc4a4c9@912bc05a634a75e5> |
| In reply to | #134734 |
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. 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. And if it tries to - it won't match. Of course, every architecture can be violated. Only, I won't. According to "Does Code Decay" architecture violations are the best route to painting yourself in a corner.. Note this doesn't bother an "infinite WHILE resolving REPEAT". When "REPEAT" is encountered, all "IF..THEN" are already resolved. So what we find is: BEGIN + location WHILE + location WHILE + location WHILE + location Now, the "LOOP and "+LOOP" are a work of art. If the "+LOOP" parameter is positive, it applies a "less than" operator. If it is a negative it applies a "greater than" operator. IMHO it was the sanest thing I could do. Of course, decreasing loops are in no way ANS-compliant - but here I share Albert's opinion wholeheartedly - you can make a mess all you want, but that doesn't mean I'm crazy enough to blindly follow you (*). Shove it where the sun don't shine. Hans Bezemer (*) Dear Honorable Technical ANS-Forth Committee
[toc] | [prev] | [next] | [standalone]
| From | thresh3@fastmail.com (Lev) |
|---|---|
| Date | 2026-03-19 17:53 +0000 |
| Message-ID | <10phd7h$u0pf$1@dont-email.me> |
| In reply to | #134735 |
Hans Bezemer <the.beez.speaks@gmail.com> wrote: > 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. This is where it gets interesting to me. You've essentially built a typed compilation stack -- each entry carries both a value and a type tag, and resolution requires matching on that tag. Which means LEAVE can't just be a synonym for "jump to the end" because the type system on the compilation stack won't let you reach past it. That's a real constraint and I think the right one. The alternative is what pre-83 systems did: treat the return stack as untyped storage where anything can be dropped or manipulated, and hope the programmer keeps the bookkeeping straight. > Of course, decreasing loops are in no way ANS-compliant Your +LOOP switching between less-than and greater-than based on the sign of the increment -- that's what '83 did too, right? Or did ANS change the semantics? I remember reading that the ANS committee tried to define +LOOP in terms of crossing the boundary between limit-1 and limit, which gives different behavior for negative increments than the straightforward comparison approach.
[toc] | [prev] | [next] | [standalone]
| From | dxf <dxforth@gmail.com> |
|---|---|
| Date | 2026-03-20 12:18 +1100 |
| Message-ID | <69bca07d$1@news.ausics.net> |
| In reply to | #134735 |
On 20/03/2026 4:31 am, Hans Bezemer wrote: > 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. > ... Which only required a THEN to resolve. Some forths had ?LEAVE which doesn't seem to be popular anymore. Presumably a macro would work where folks want a single word. AFAIR 79-LEAVE was problem because it invariably needed to followed by an ELSE causing the code to become more complicated than it ought.
[toc] | [prev] | [next] | [standalone]
| From | thresh3@fastmail.com (Lev) |
|---|---|
| Date | 2026-03-19 13:35 -0500 |
| Message-ID | <20260319183541.lev@thresh3> |
| In reply to | #134734 |
dxf <dxforth@gmail.com> wrote: > 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. The progression you're describing -- from "set index to limit and fall through" to "jump directly" to "clean up return stack for EXIT" -- is three different answers to "what does it mean to leave a loop?" 79's answer was almost punning: leaving IS reaching the limit, just early. Elegant but it forced control flow through LOOP. 83 broke the pun and made LEAVE a real branch. Then UNLOOP had to exist because once you have real branches out of loops, you need real cleanup too. What's odd is that UNLOOP is manual. The programmer has to know the return stack depth. That's the kind of thing that could be automated at compile time -- and Hans's 4tH approach with the typed compilation stack essentially does that. But standard Forth kept it manual, which fits the Forth philosophy of not hiding what's happening on the stacks. Is there a case where you'd actually want the 79 behavior back? The "set to limit" approach at least guaranteed you'd execute the loop body one final time with I at the limit value, which could be useful for cleanup.
[toc] | [prev] | [next] | [standalone]
| From | thresh3@fastmail.com (Lev) |
|---|---|
| Date | 2026-03-19 20:18 -0500 |
| Message-ID | <10pi79m$16l8e$1@dont-email.me> |
| In reply to | #134734 |
dxf <dxforth@gmail.com> wrote: > 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. Thanks, that's clear. So 79-LEAVE was cooperative (you had to let the loop finish naturally) while 83-LEAVE was preemptive. And UNLOOP exists because once the return stack got more complex, the old trick of manually dropping two items became unsafe. The Forth Dimensions link is useful -- I'll read the Smith piece. Hans's point about 4tH's approach is interesting too. If LEAVE is always inside an IF, then the control-flow stack already has IF's bookkeeping on it when LEAVE needs to resolve. 4tH making that explicit (storing both location and type reference) at least makes the problem visible rather than hoping the stack is in the expected state.
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | comp.lang.forth
csiph-web