Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.forth > #37626 > unrolled thread

Re: Forth loops don't inherently loop once

Started byhughaguilar96@gmail.com
First post2015-03-24 21:42 -0700
Last post2015-04-11 15:04 +0200
Articles 11 — 7 participants

Back to article view | Back to comp.lang.forth

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: Forth loops don't inherently loop once hughaguilar96@gmail.com - 2015-03-24 21:42 -0700
    Re: Forth loops don't inherently loop once Ron Aaron <rambamist@gmail.com> - 2015-03-25 07:54 +0200
      Re: Forth loops don't inherently loop once "Alex McDonald" <blog@rivadpm.com> - 2015-03-25 07:33 +0000
        Re: Forth loops don't inherently loop once Ron Aaron <rambamist@gmail.com> - 2015-03-25 09:43 +0200
          Re: Forth loops don't inherently loop once "Rod Pemberton" <bork@lllljunkqwer.cpm> - 2015-03-28 03:35 -0400
            Re: Forth loops don't inherently loop once Ron Aaron <rambamist@gmail.com> - 2015-03-28 20:31 +0300
    Re: Forth loops don't inherently loop once "WJ" <w_a_x_man@yahoo.com> - 2015-03-25 06:19 +0000
    Re: Forth loops don't inherently loop once Hans Bezemer <the.beez.speaks@gmail.com> - 2015-04-10 17:34 +0200
      Re: Forth loops don't inherently loop once Coos Haak <chforth@hccnet.nl> - 2015-04-11 00:24 +0200
        Re: Forth loops don't inherently loop once hughaguilar96@gmail.com - 2015-04-10 18:59 -0700
        Re: Forth loops don't inherently loop once Hans Bezemer <the.beez.speaks@gmail.com> - 2015-04-11 15:04 +0200

#37626 — Re: Forth loops don't inherently loop once

Fromhughaguilar96@gmail.com
Date2015-03-24 21:42 -0700
SubjectRe: Forth loops don't inherently loop once
Message-ID<08127e8c-cc3b-4d53-a9a1-2ac733df7c97@googlegroups.com>
On Wednesday, August 7, 2013 at 11:25:21 AM UTC-7, Elizabeth D. Rather wrote:
> On 8/7/13 1:46 AM, Mark Wills wrote:
> > Er, exactly what problem is this trying to solve? I'm at a total loss here.

I don't know what he's talking about either.

BTW: Some ANS-Forth cruft that I will get rid of in my language, is UNTIL and AGAIN. All that is needed is BEGIN WHILE REPEAT with any number of WHILE (including zero, so BEGIN REPEAT does what BEGIN AGAIN currently does).

> Forth offers both test-at-the-beginning loops and test-at-the-end loops:

I don't like to expose any kind of loop to the application programmer, especially the novice. It should be possible to write most programs without any kind of explicit iteration. In my language, loops will be considered to be expert-only programming --- the only loop mechanisms provided will be BEGIN WHILE REPEAT and recursion, and the novice will be encouraged to not learn either of these until he has some experience writing programs (has written several non-trivial programs).

ANS-Forth is very crude in that it requires the programmer to write loops manually. Iteration just complicates programs and makes them hard to read. As much as possible, iteration should hidden inside of higher-order functions (and leave it to the experts to write these) --- the typical programmer shouldn't have to deal with explicit loops and the testing of an index to a limit, either at the beginning or the end or the middle either.

Loops are a major source of bugs. It is very common to write a loop that executes one too many times. Also, it is difficult to look at a loop in the source-code and tell at a glance how many times it will execute, and if this is the correct number of times. Because of this, programmers should avoid writing loops, and leave that to the experts --- the ideal should be that most programs have no loops at all --- even after the programmer becomes an expert, he should eschew iteration in order to avoid bugs and increase readability.

[toc] | [next] | [standalone]


#37629

FromRon Aaron <rambamist@gmail.com>
Date2015-03-25 07:54 +0200
Message-ID<metihq$fk$1@dont-email.me>
In reply to#37626

On 3/25/15 06:42, hughaguilar96@gmail.com wrote:

> I don't like to expose any kind of loop to the application programmer, especially the novice. It should be possible to write most programs without any kind of explicit iteration. In my language, loops will be considered to be expert-only programming --- the only loop mechanisms provided will be BEGIN WHILE REPEAT and recursion, and the novice will be encouraged to not learn either of these until he has some experience writing programs (has written several non-trivial programs).

Well, that certainly is a unique approach.  I think you'll find that
most real-world programs will need iteration of some kind.  Making that
easy for the user will make your users less frustrated when they try to
actually *do* something with your language.

It's also a good idea to stop categorizing your users as 'novice' or
'expert' programmers.  Help all of them to become 'competent' users of
your system.

8th (8th-dev.com) has a number of looping constructs, serving different
needs.  'loop' and 'loop-' are analogues of a typical 'for loop' in most
languages, e.g.

' someword 1 10 loop

It also has 'repeat...again' and 'repeat ... while' (no 'begin' word)
which are familiar to most Forthers.

There is also 'times' which does not provide the current iteration index:

' someword 5 times

Containers like arrays and objects have 'each':

[1,20,300]  ' on-each-item  a:each

In all of these scenarios, invoking 'break' in the iterator will make
the current iteration the last one to execute.

And you can also use the recursive iteration technique familiar from Forth:

: xyzzy .... recurse ;

[toc] | [prev] | [next] | [standalone]


#37633

From"Alex McDonald" <blog@rivadpm.com>
Date2015-03-25 07:33 +0000
Message-ID<meto9s$fv5$1@dont-email.me>
In reply to#37629
on 25/03/2015 05:54:48, Ron Aaron wrote:
> 
> 
> On 3/25/15 06:42, hughaguilar96@gmail.com wrote:
> 
>> I don't like to expose any kind of loop to the application programmer, especially the novice. It 
should be possible to write most programs without any kind of explicit
iteration. In my language, loops will be considered to be expert-only
programming --- the only loop mechanisms provided will be BEGIN WHILE
REPEAT and recursion, and the novice will be encouraged to not learn
either of these until he has some experience writing programs (has
written several non-trivial programs). > 
> Well, that certainly is a unique approach.  I think you'll find that
> most real-world programs will need iteration of some kind. Making that
> easy for the user will make your users less frustrated when they try
> to actually *do* something with your language.
> 

Hugh's loop appears to be repeating the claim that he has a language. 

[toc] | [prev] | [next] | [standalone]


#37634

FromRon Aaron <rambamist@gmail.com>
Date2015-03-25 09:43 +0200
Message-ID<metotg$hmn$1@dont-email.me>
In reply to#37633

On 3/25/15 09:33, Alex McDonald wrote:

> Hugh's loop appears to be repeating the claim that he has a language. 

To be fair, he only claims what his language *will* have...

[toc] | [prev] | [next] | [standalone]


#37701

From"Rod Pemberton" <bork@lllljunkqwer.cpm>
Date2015-03-28 03:35 -0400
Message-ID<op.xv651ublwa0t4m@localhost>
In reply to#37634
On Wed, 25 Mar 2015 03:43:31 -0400, Ron Aaron <rambamist@gmail.com> wrote:
> On 3/25/15 09:33, Alex McDonald wrote:

>> Hugh's loop appears to be repeating the claim that he has a language.
>
> To be fair, he only claims what his language *will* have...

I don't know why this is taking him so long ...  Do you?


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#37711

FromRon Aaron <rambamist@gmail.com>
Date2015-03-28 20:31 +0300
Message-ID<mf6ofo$pef$1@dont-email.me>
In reply to#37701

On 3/28/15 10:35, Rod Pemberton wrote:

> I don't know why this is taking him so long ...  Do you?

Dunno.  He's not confided in me...

[toc] | [prev] | [next] | [standalone]


#37630

From"WJ" <w_a_x_man@yahoo.com>
Date2015-03-25 06:19 +0000
Message-ID<metk11$4bg$1@dont-email.me>
In reply to#37626
hughaguilar96@gmail.com wrote:

> I don't like to expose any kind of loop to the
> application programmer, especially the novice. It
> should be possible to write most programs without
> any kind of explicit iteration. In my language,
> loops will be considered to be expert-only
> programming --- the only loop mechanisms provided
> will be BEGIN WHILE REPEAT and recursion, and the
> novice will be encouraged to not learn either of
> these until he has some experience writing
> programs (has written several non-trivial
> programs).
> 
> ANS-Forth is very crude in that it requires the
> programmer to write loops manually. Iteration just
> complicates programs and makes them hard to read.
> As much as possible, iteration should hidden
> inside of higher-order functions (and leave it to
> the experts to write these) --- the typical
> programmer shouldn't have to deal with explicit
> loops and the testing of an index to a limit,
> either at the beginning or the end or the middle
> either.
> 
> Loops are a major source of bugs. It is very
> common to write a loop that executes one too many
> times. Also, it is difficult to look at a loop in
> the source-code and tell at a glance how many
> times it will execute, and if this is the correct
> number of times. Because of this, programmers
> should avoid writing loops, and leave that to the
> experts --- the ideal should be that most programs
> have no loops at all --- even after the programmer
> becomes an expert, he should eschew iteration in
> order to avoid bugs and increase readability.

There is a lot of truth in this.

One of the gurus in the K (or Q) language (similar to J and APL)
has a motto: "We don't need no stinkin' loops!"

Some examples in Oforth.

Say you have a list or array of numbers, and you want to
create a new list by incrementing each number. We don't
explicitly loop, we just use the higher-order function "map",
which is also found in Scheme, Lisp, Ruby, etc. (Think of a
one-to-one mapping.)

> seq( 9 ) dup println map( #++ ) println
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[2, 3, 4, 5, 6, 7, 8, 9, 10]

> "ABCDE" map( #[ 32 + ] ) charsAsString println
abcde


Say you have a sequence of numbers, and you want to
keep only the odd ones:

> 22 seq filter( #isOdd ) println
[1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21]


Say you have two sequences, and you want to pair
the elements:

> [ 2, 3, 4, 5 ] [ "or", "a", "big", "why" ] zip println
[[2, or], [3, a], [4, big], [5, why]]


Say you want to add up the numbers in a list.
(Oforth has the command "sum", but we'll do it
the hard way.)

> 0 [ 1, 3, 5, 7, 9 ] apply( #+ ) println
25

Another way:

> [ 1, 3, 5, 7, 9 ] reduce( #+ ) println
25


To execute code a certain number of times:

> #[ "Hello" println ] times( 3 )
Hello
Hello
Hello

> 2 #sq times( 3 ) println
256

[toc] | [prev] | [next] | [standalone]


#38085

FromHans Bezemer <the.beez.speaks@gmail.com>
Date2015-04-10 17:34 +0200
Message-ID<5527ed9b$0$2937$e4fe514c@news2.news.xs4all.nl>
In reply to#37626
hughaguilar96@gmail.com wrote:
> BTW: Some ANS-Forth cruft that I will get rid of in my language, is UNTIL
> and AGAIN. All that is needed is BEGIN WHILE REPEAT with any number of
> WHILE (including zero, so BEGIN REPEAT does what BEGIN AGAIN currently
> does).

I like your thinking. That's exactly what I did in 4tH: as many WHILE's as
you like (without ugly THEN's) and REPEAT and AGAIN are aliases. I kept
UNTIL though, since it is just a "0BRANCH" instead of a "BRANCH"
(REPEAT/AGAIN). The idea is not new though. I can remember somebody writing
an article on the same thing in FD.

I added another construct, which is "DONE". A "DONE" is connected to the
last "WHILE" defined and is triggered when that "WHILE" condition fails.
E.g.

---8<---
: test begin dup while 1- done . done ." Not ready yet!" cr repeat ; 

5 test Not ready yet!
Not ready yet!
Not ready yet!
Not ready yet!
Not ready yet!
0  ok 
---8<---

In ANS it is defined as:

---8<---
: DONE 1 CS-ROLL POSTPONE ELSE 1 CS-ROLL ; IMMEDIATE
---8<---

It is especially handy when the stack is different between several WHILE's,
because you can clean it up in specific ways before leaving instead of
dumping and dropping useless items on the stack, just to keep it balanced.

It is interesting to see what it compiles to (gForth):
see test
: test
  BEGIN  dup
         IF     1-
         ELSE   .
         ELSE   .\" Not ready yet!" cr
         REPEAT 

or 4tH:

4tH message: No errors at word 11
Object size: 11 words
String size: 15 chars
Variables  : 0 cells
Strings    : 0 chars
Reliable   : Yes

[   0] branch      (11)
[   1] dup         (0)
[   2] 0branch     (5)
[   3] +literal    (-1)
[   4] branch      (7)
[   5] .           (0)
[   6] branch      (10)
[   7] ."          (0)  Not ready yet!
[   8] cr          (0)
[   9] branch      (1)
[  10] exit        (0)

BTW, a single "DONE" is a "NOOP".

May be this gives you some extra inspiration! ;-)

Hans Bezemer

[toc] | [prev] | [next] | [standalone]


#38108

FromCoos Haak <chforth@hccnet.nl>
Date2015-04-11 00:24 +0200
Message-ID<4g7c0krzd9tp.1lr72gfa11oid.dlg@40tude.net>
In reply to#38085
Op Fri, 10 Apr 2015 17:34:43 +0200 schreef Hans Bezemer:

> hughaguilar96@gmail.com wrote:
>> BTW: Some ANS-Forth cruft that I will get rid of in my language, is UNTIL
>> and AGAIN. All that is needed is BEGIN WHILE REPEAT with any number of
>> WHILE (including zero, so BEGIN REPEAT does what BEGIN AGAIN currently
>> does).
> 
> I like your thinking. That's exactly what I did in 4tH: as many WHILE's as
> you like (without ugly THEN's) and REPEAT and AGAIN are aliases. I kept
> UNTIL though, since it is just a "0BRANCH" instead of a "BRANCH"
> (REPEAT/AGAIN). The idea is not new though. I can remember somebody writing
> an article on the same thing in FD.
> 
> I added another construct, which is "DONE". A "DONE" is connected to the
> last "WHILE" defined and is triggered when that "WHILE" condition fails.
> E.g.
> 
> ---8<---
>: test begin dup while 1- done . done ." Not ready yet!" cr repeat ; 
> 
> 5 test Not ready yet!
> Not ready yet!
> Not ready yet!
> Not ready yet!
> Not ready yet!
> 0  ok 
> ---8<---
> 
> In ANS it is defined as:
> 
> ---8<---
>: DONE 1 CS-ROLL POSTPONE ELSE 1 CS-ROLL ; IMMEDIATE
> ---8<---
> 
> It is especially handy when the stack is different between several WHILE's,
> because you can clean it up in specific ways before leaving instead of
> dumping and dropping useless items on the stack, just to keep it balanced.
> 
> It is interesting to see what it compiles to (gForth):
> see test
>: test
>   BEGIN  dup
>          IF     1-
>          ELSE   .
>          ELSE   .\" Not ready yet!" cr
>          REPEAT 
> 
> or 4tH:
> 
> 4tH message: No errors at word 11
> Object size: 11 words
> String size: 15 chars
> Variables  : 0 cells
> Strings    : 0 chars
> Reliable   : Yes
> 
> [   0] branch      (11)
> [   1] dup         (0)
> [   2] 0branch     (5)
> [   3] +literal    (-1)
> [   4] branch      (7)
> [   5] .           (0)
> [   6] branch      (10)
> [   7] ."          (0)  Not ready yet!
> [   8] cr          (0)
> [   9] branch      (1)
> [  10] exit        (0)
> 
> BTW, a single "DONE" is a "NOOP".
> 
> May be this gives you some extra inspiration! ;-)
> 
> Hans Bezemer

It's the old multiple ELSE trick:
.. if .. else .. else .. else .. then ..

And what's the advantage above
: test begin dup while 1- ." Not ready yet!" cr repeat . ; 

-- 
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html 

[toc] | [prev] | [next] | [standalone]


#38110

Fromhughaguilar96@gmail.com
Date2015-04-10 18:59 -0700
Message-ID<48b3cf51-3cc0-4364-a63e-9a585152e343@googlegroups.com>
In reply to#38108
On Friday, April 10, 2015 at 3:34:04 PM UTC-7, Coos Haak wrote:
> Op Fri, 10 Apr 2015 17:34:43 +0200 schreef Hans Bezemer:
> 
> > hughaguilar96@gmail.com wrote:
> >> BTW: Some ANS-Forth cruft that I will get rid of in my language, is UNTIL
> >> and AGAIN. All that is needed is BEGIN WHILE REPEAT with any number of
> >> WHILE (including zero, so BEGIN REPEAT does what BEGIN AGAIN currently
> >> does).
> > 
> > I like your thinking. That's exactly what I did in 4tH: as many WHILE's as
> > you like (without ugly THEN's) and REPEAT and AGAIN are aliases. I kept
> > UNTIL though, since it is just a "0BRANCH" instead of a "BRANCH"
> > (REPEAT/AGAIN). The idea is not new though. I can remember somebody writing
> > an article on the same thing in FD.
> > 
> > I added another construct, which is "DONE". A "DONE" is connected to the
> > last "WHILE" defined and is triggered when that "WHILE" condition fails.
> > E.g.
> > 
> > ---8<---
> >: test begin dup while 1- done . done ." Not ready yet!" cr repeat ; 
> > 
> > 5 test Not ready yet!
> > Not ready yet!
> > Not ready yet!
> > Not ready yet!
> > Not ready yet!
> > 0  ok 
> > ---8<---
> > 
> > In ANS it is defined as:
> > 
> > ---8<---
> >: DONE 1 CS-ROLL POSTPONE ELSE 1 CS-ROLL ; IMMEDIATE
> > ---8<---
> > 
> > It is especially handy when the stack is different between several WHILE's,
> > because you can clean it up in specific ways before leaving instead of
> > dumping and dropping useless items on the stack, just to keep it balanced.
> > 
> > It is interesting to see what it compiles to (gForth):
> > see test
> >: test
> >   BEGIN  dup
> >          IF     1-
> >          ELSE   .
> >          ELSE   .\" Not ready yet!" cr
> >          REPEAT 
> > 
> > or 4tH:
> > 
> > 4tH message: No errors at word 11
> > Object size: 11 words
> > String size: 15 chars
> > Variables  : 0 cells
> > Strings    : 0 chars
> > Reliable   : Yes
> > 
> > [   0] branch      (11)
> > [   1] dup         (0)
> > [   2] 0branch     (5)
> > [   3] +literal    (-1)
> > [   4] branch      (7)
> > [   5] .           (0)
> > [   6] branch      (10)
> > [   7] ."          (0)  Not ready yet!
> > [   8] cr          (0)
> > [   9] branch      (1)
> > [  10] exit        (0)
> > 
> > BTW, a single "DONE" is a "NOOP".
> > 
> > May be this gives you some extra inspiration! ;-)
> > 
> > Hans Bezemer
> 
> It's the old multiple ELSE trick:
> .. if .. else .. else .. else .. then ..
 
> And what's the advantage above
> : test begin dup while 1- ." Not ready yet!" cr repeat . ; 

The Beez' code does something (prints the index) for the last iteration, which your code doesn't do.

I don't think I'll add DONE to my language though. Instead, I would provide this word:

: looper ( initial 'toucher -- )           
\ the toucher must have this stack frame:  index -- new-index continue?
    >r begin  r@ execute while repeat drop
    r> drop ;

The user can then write his own toucher like this:

: beez-example ( index -- new-index continue? )
    1- >r
    r@ 0= if  cr r@ .           r>  false   exit then
    cr ." not done yet!"        r>  true ;

Here is an example usage (tested under VFX):

5 ' beez-example looper 
not done yet!
not done yet!
not done yet!
not done yet!
0  ok

LOOPER is more general purpose. The toucher adjusts the index at the beginning, and it does something depending upon what the index is. The example above is pretty simple because there is only one special-case --- the index being zero --- but it is possible to have several special-cases. Also, it is possible to have several ways of adjusting the index --- it can go up or down, and not always by the same amount --- any manner of complexity is possible.

There is a common theme throughout the novice-package: I try to hide iteration as much as possible --- I don't want the programmer to have to use BEGIN loops explicitly at all. I prefer to have the programmer pass the xt of a function into a higher-order function that contains the loop, so the BEGIN or whatever is hidden in the higher-order function --- the fewer explicit loops that there are in the application program, the more readable the application program will be. :-) LOOPER is actually pretty useful --- I think I will add this to the novice-package.

[toc] | [prev] | [next] | [standalone]


#38124

FromHans Bezemer <the.beez.speaks@gmail.com>
Date2015-04-11 15:04 +0200
Message-ID<55291c00$0$2831$e4fe514c@news2.news.xs4all.nl>
In reply to#38108
Coos Haak wrote:
> It's the old multiple ELSE trick:
> .. if .. else .. else .. else .. then ..
> 
> And what's the advantage above
> : test begin dup while 1- ." Not ready yet!" cr repeat . ;
NOTHING! Because it only features one WHILE. However, in 4tH it is not
unusual to have multiple WHILEs, e.g.

BEGIN cond1 WHILE cond2 WHILE body REPEAT

As in:
                                       \ reload entire index
: (reload)                             ( h ix -- h ix n)
  dup -> (isiz) @ cells over + (ihead) + >r dup (ihead) +
  begin                                ( h ix ix-body r: ix-top)
    refill                             \ get the next line
  while                                \ if successful
    dup r@ <                           \ check limit
  while                                \ if successful
    (number?) 0= >r over ! r>          \ save index value
  while                                \ if a positive number
    cell+                              \ move to next cell
  repeat                               \ until some kind of error occurs
  r> drop over (ihead) + -             \ leave size ( h ix n)
;

Or:

: (convert)                            ( a1 n1 n2 -- a2 n3 n4 n5)
  0 >r >r                              \ setup exponent, save accu
  begin
    over over                          \ is there any string left?
  while                                \ if so, get digit and compare
    c@ [char] 0 - dup 0< over 9 > or 0= r@ (limit) < and
  while                                \ don't cross the cell boundary
    r> 10 * + r> 1+ >r >r chop         \ shift left, increment exponent
  repeat drop r> r>                    \ drop value, get accu and exponent
;

(Note the neat trick where I use the count at one place and the address in
the next).

In this case I was able to get the stack diagram identical at all the WHILE
parts. But sometimes, you can't. In that case you can use a DONE to correct
it.

Hans Bezemer

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.forth


csiph-web