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


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

Simple Forth problem

Started by"WJ" <w_a_x_man@yahoo.com>
First post2013-09-17 09:39 +0000
Last post2013-09-18 14:22 +1000
Articles 12 — 9 participants

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


Contents

  Simple Forth problem "WJ" <w_a_x_man@yahoo.com> - 2013-09-17 09:39 +0000
    Re: Simple Forth problem VoidVolker <voidvolker@gmail.com> - 2013-09-17 03:28 -0700
      Re: Simple Forth problem Coos Haak <chforth@hccnet.nl> - 2013-09-17 17:05 +0200
        Re: Simple Forth problem "Alex McDonald" <blog@rivadpm.com> - 2013-09-17 16:53 +0100
        Re: Simple Forth problem Howerd <howerdo@yahoo.co.uk> - 2013-09-17 09:18 -0700
    Re: Simple Forth problem VoidVolker <voidvolker@gmail.com> - 2013-09-17 11:06 -0700
      Re: Simple Forth problem Alex McDonald <blog@rivadpm.com> - 2013-09-17 12:13 -0700
        Re: Simple Forth problem VoidVolker <voidvolker@gmail.com> - 2013-09-17 22:42 -0700
          Re: Simple Forth problem mhx@iae.nl - 2013-09-18 00:00 -0700
      Re: Simple Forth problem Howerd <howerdo@yahoo.co.uk> - 2013-09-17 13:26 -0700
      Re: Simple Forth problem Doug Hoffman <glidedog@gmail.com> - 2013-09-18 08:42 -0400
    Re: Simple Forth problem "Ed" <invalid@invalid.com> - 2013-09-18 14:22 +1000

#25719 — Simple Forth problem

From"WJ" <w_a_x_man@yahoo.com>
Date2013-09-17 09:39 +0000
SubjectSimple Forth problem
Message-ID<l19804$g8k$1@dont-email.me>
Make a list of the elements that are found in both lists
at the same index.

OCaml:


open List;;
map fst
  (filter (fun (x,y) -> x=y)
          (combine [3;5;7;8;12] [2;5;8;10;12]));;

[5; 12]


Using the piping operator (|>):


combine [3;5;7;8;12] [2;5;8;10;12] |>
filter (fun (x,y) -> x=y) |>
map fst ;;


Since every gavino "knows" that Forth amplifies programmer productivity,
let's see several Forth solutions that are more concise than the
OCaml ones.

[toc] | [next] | [standalone]


#25721

FromVoidVolker <voidvolker@gmail.com>
Date2013-09-17 03:28 -0700
Message-ID<844c148c-849f-4f6b-9b09-f78894f34c47@googlegroups.com>
In reply to#25719
вторник, 17 сентября 2013 г., 13:39:17 UTC+4 пользователь WJ написал:
> Make a list of the elements that are found in both lists
> 
> at the same index.
> 
> 
> 
> OCaml:
> 
> 
> 
> 
> 
> open List;;
> 
> map fst
> 
>   (filter (fun (x,y) -> x=y)
> 
>           (combine [3;5;7;8;12] [2;5;8;10;12]));;
> 
> 
> 
> [5; 12]
> 
> 
> 
> 
> 
> Using the piping operator (|>):
> 
> 
> 
> 
> 
> combine [3;5;7;8;12] [2;5;8;10;12] |>
> 
> filter (fun (x,y) -> x=y) |>
> 
> map fst ;;
> 
> 
> 
> 
> 
> Since every gavino "knows" that Forth amplifies programmer productivity,
> 
> let's see several Forth solutions that are more concise than the
> 
> OCaml ones.

http://www.nncron.ru/download/plugins/vv/lists.spf

For named lists:

    LIST: l1
    LIST: l2
    l1[ 3 5 7 8 12 ]l1
    l2[ 2 5 8 10 12 ]l2
    : lists-compare
      l1-- l2--   \ Init list iterators
      BEGIN     \ Start cicle
        l1@ 0<>     \ ?     \ Compare curent node value of l1 with 0
        l2@ 0<>     \ ? ?   \ Compare curent node value of l2 with 0
        AND         \ ?     \
      WHILE     \ Cicle rule
        l1@ l2@ =   \ ?     \ Compare curent node values of lists
        IF              \ Check the flag on stack 
          l1@ .           \ And do some actions
        THEN            \ Actions end
        l1> l2>     \ Switch list iterators to next nodes
      REPEAT    \ Cicle end
    ;

Start the code in console:
    lists-compare
    5 12  Ok

For noname lists:

    : lists-compare2   { l1 l2 -- }
      l1 LIST--   l2 LIST--
      BEGIN
        l1 LIST@  0<>
        l2 LIST@  0<> 
        AND
      WHILE
        l1 LIST@
        l2 LIST@
        = IF
          l1 LIST@ .
        THEN
        l1 LIST>
        l2 LIST>
      REPEAT
    ;

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


#25724

FromCoos Haak <chforth@hccnet.nl>
Date2013-09-17 17:05 +0200
Message-ID<hronr1bdzw8s$.i7lpb9cr071t.dlg@40tude.net>
In reply to#25721
Op Tue, 17 Sep 2013 03:28:52 -0700 (PDT) schreef VoidVolker:

> вторник, 17 сентября 2013 г., 13:39:17 UTC+4 пользователь WJ написал:
>> Make a list of the elements that are found in both lists
>> 
>> at the same index.
>> 
>> 
>> 
>> OCaml:
>> 
>> 
>> 
>> 
>> 
>> open List;;
>> 
>> map fst
>> 
>>   (filter (fun (x,y) -> x=y)
>> 
>>           (combine [3;5;7;8;12] [2;5;8;10;12]));;
>> 
>> 
>> 
>> [5; 12]
>> 
>> 
>> 
>> 
>> 
>> Using the piping operator (|>):
>> 
>> 
>> 
>> 
>> 
>> combine [3;5;7;8;12] [2;5;8;10;12] |>
>> 
>> filter (fun (x,y) -> x=y) |>
>> 
>> map fst ;;
>> 
>> 
>> 
>> 
>> 
>> Since every gavino "knows" that Forth amplifies programmer productivity,
>> 
>> let's see several Forth solutions that are more concise than the
>> 
>> OCaml ones.
> 
> http://www.nncron.ru/download/plugins/vv/lists.spf
> 
> For named lists:
> 
>     LIST: l1
>     LIST: l2
>     l1[ 3 5 7 8 12 ]l1
>     l2[ 2 5 8 10 12 ]l2
>     : lists-compare
>       l1-- l2--   \ Init list iterators
>       BEGIN     \ Start cicle
>         l1@ 0<>     \ ?     \ Compare curent node value of l1 with 0
>         l2@ 0<>     \ ? ?   \ Compare curent node value of l2 with 0
>         AND         \ ?     \
>       WHILE     \ Cicle rule
>         l1@ l2@ =   \ ?     \ Compare curent node values of lists
>         IF              \ Check the flag on stack 
>           l1@ .           \ And do some actions
>         THEN            \ Actions end
>         l1> l2>     \ Switch list iterators to next nodes
>       REPEAT    \ Cicle end
>     ;
> 
> Start the code in console:
>     lists-compare
>     5 12  Ok
> 
> For noname lists:
> 
>     : lists-compare2   { l1 l2 -- }
>       l1 LIST--   l2 LIST--
>       BEGIN
>         l1 LIST@  0<>
>         l2 LIST@  0<> 
>         AND
>       WHILE
>         l1 LIST@
>         l2 LIST@
>         = IF
>           l1 LIST@ .
>         THEN
>         l1 LIST>
>         l2 LIST>
>       REPEAT
>     ;

create l1   3 , 5 , 7 , 8 , 12 , 0 ,
create l2   2 , 5 , 8 , 10 , 12 , 0 ,

: lists-compare
        l1 l2
        begin   over @ 0<> over @ 0<> and
        while   over @ over @ =
                if      dup @ .
                then
                cell+ swap cell+ swap
        repeat
        2drop
;

lists-compare
5 12 ok

-- 
Coos

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

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


#25726

From"Alex McDonald" <blog@rivadpm.com>
Date2013-09-17 16:53 +0100
Message-ID<l19tt1$fvn$1@dont-email.me>
In reply to#25724
on 17/09/2013 16:05:48, Coos Haak wrote:
> Op Tue, 17 Sep 2013 03:28:52 -0700 (PDT) schreef VoidVolker:
> 
>> вторник, 17 сентября 2013 г., 13:39:17 UTC+4 пользователь WJ написал:
>>> Make a list of the elements that are found in both lists
>>>
>>> at the same index.
>>>
>>>
>>>
>>> OCaml:
>>>
>>>
>>>
>>>
>>>
>>> open List;;
>>>
>>> map fst
>>>
>>>   (filter (fun (x,y) -> xy)
>>>
>>>           (combine [3;5;7;8;12] [2;5;8;10;12]));;
>>>
>>>
>>>
>>> [5; 12]
>>>
>>>
>>>
>>>
>>>
>>> Using the piping operator (|>):
>>>
>>>
>>>
>>>
>>>
>>> combine [3;5;7;8;12] [2;5;8;10;12] |>
>>>
>>> filter (fun (x,y) -> xy) |>
>>>
>>> map fst ;;
>>>
>>>
>>>
>>>
>>>
>>> Since every gavino "knows" that Forth amplifies programmer productivity,
>>>
>>> let's see several Forth solutions that are more concise than the
>>>
>>> OCaml ones.
>>
>> http://www.nncron.ru/download/plugins/vv/lists.spf>
>> For named lists:
>>
>>     LIST: l1
>>     LIST: l2
>>     l1[ 3 5 7 8 12 ]l1
>>     l2[ 2 5 8 10 12 ]l2
>>     : lists-compare
>>       l1-- l2--   \ Init list iterators
>>       BEGIN     \ Start cicle
>>         l1@ 0<>     \ ?     \ Compare curent node value of l1 with 0
>>         l2@ 0<>     \ ? ?   \ Compare curent node value of l2 with 0
>>         AND         \ ?     \
>>       WHILE     \ Cicle rule
>>         l1@ l2@    \ ?     \ Compare curent node values of lists
>>         IF              \ Check the flag on stack
>>           l1@ .           \ And do some actions
>>         THEN            \ Actions end
>>         l1> l2>     \ Switch list iterators to next nodes
>>       REPEAT    \ Cicle end
>>     ;
>>
>> Start the code in console:
>>     lists-compare
>>     5 12  Ok
>>
>> For noname lists:
>>
>>     : lists-compare2   { l1 l2 -- }
>>       l1 LIST--   l2 LIST--
>>       BEGIN
>>         l1 LIST@  0<>
>>         l2 LIST@  0<>
>>         AND
>>       WHILE
>>         l1 LIST@
>>         l2 LIST@
>>          IF
>>           l1 LIST@ .
>>         THEN
>>         l1 LIST>
>>         l2 LIST>
>>       REPEAT
>>     ;
> 
> create l1   3 , 5 , 7 , 8 , 12 , 0 ,
> create l2   2 , 5 , 8 , 10 , 12 , 0 ,
> 
>: lists-compare
> l1 l2
> begin   over @ 0<> over @ 0<> and
> while   over @ over @
> if      dup @ .
> then
> cell+ swap cell+ swap
> repeat
> 2drop
> ;
> 
> lists-compare
> 5 12 ok
> 
> --
> Coos
> 
> CHForth, 16 bit DOS applications
> http://home.hccnet.nl/j.j.haak/forth.html

create l1   3 , 5 , 7 , 8 , 12 , 0 ,
create l2   2 , 5 , 8 , 10 , 12 , 0 ,

: lists-compare
        begin   2dup @ swap @ 2dup *
        while   over - if drop else . then
                cell+ swap cell+
        repeat
        2drop
;

cr l1 l2 lists-compare
\ 5 12 ok

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


#25727

FromHowerd <howerdo@yahoo.co.uk>
Date2013-09-17 09:18 -0700
Message-ID<91dd9af4-ce12-4a62-9519-6f999ef0e9ef@googlegroups.com>
In reply to#25724
On Tuesday, September 17, 2013 4:05:47 PM UTC+1, Coos Haak wrote:
> Op Tue, 17 Sep 2013 03:28:52 -0700 (PDT) schreef VoidVolker:
> 
> 
> 
> > вторник, 17 сентября 2013 г., 13:39:17 UTC+4 пользователь WJ написал:
> 
> >> Make a list of the elements that are found in both lists
> 
> >> 
> 
> >> at the same index.
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> OCaml:
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> open List;;
> 
> >> 
> 
> >> map fst
> 
> >> 
> 
> >>   (filter (fun (x,y) -> x=y)
> 
> >> 
> 
> >>           (combine [3;5;7;8;12] [2;5;8;10;12]));;
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> [5; 12]
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> Using the piping operator (|>):
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> combine [3;5;7;8;12] [2;5;8;10;12] |>
> 
> >> 
> 
> >> filter (fun (x,y) -> x=y) |>
> 
> >> 
> 
> >> map fst ;;
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> 
> 
> >> Since every gavino "knows" that Forth amplifies programmer productivity,
> 
> >> 
> 
> >> let's see several Forth solutions that are more concise than the
> 
> >> 
> 
> >> OCaml ones.
> 
> > 
> 
> > http://www.nncron.ru/download/plugins/vv/lists.spf
> 
> > 
> 
> > For named lists:
> 
> > 
> 
> >     LIST: l1
> 
> >     LIST: l2
> 
> >     l1[ 3 5 7 8 12 ]l1
> 
> >     l2[ 2 5 8 10 12 ]l2
> 
> >     : lists-compare
> 
> >       l1-- l2--   \ Init list iterators
> 
> >       BEGIN     \ Start cicle
> 
> >         l1@ 0<>     \ ?     \ Compare curent node value of l1 with 0
> 
> >         l2@ 0<>     \ ? ?   \ Compare curent node value of l2 with 0
> 
> >         AND         \ ?     \
> 
> >       WHILE     \ Cicle rule
> 
> >         l1@ l2@ =   \ ?     \ Compare curent node values of lists
> 
> >         IF              \ Check the flag on stack 
> 
> >           l1@ .           \ And do some actions
> 
> >         THEN            \ Actions end
> 
> >         l1> l2>     \ Switch list iterators to next nodes
> 
> >       REPEAT    \ Cicle end
> 
> >     ;
> 
> > 
> 
> > Start the code in console:
> 
> >     lists-compare
> 
> >     5 12  Ok
> 
> > 
> 
> > For noname lists:
> 
> > 
> 
> >     : lists-compare2   { l1 l2 -- }
> 
> >       l1 LIST--   l2 LIST--
> 
> >       BEGIN
> 
> >         l1 LIST@  0<>
> 
> >         l2 LIST@  0<> 
> 
> >         AND
> 
> >       WHILE
> 
> >         l1 LIST@
> 
> >         l2 LIST@
> 
> >         = IF
> 
> >           l1 LIST@ .
> 
> >         THEN
> 
> >         l1 LIST>
> 
> >         l2 LIST>
> 
> >       REPEAT
> 
> >     ;
> 
> 
> 
> create l1   3 , 5 , 7 , 8 , 12 , 0 ,
> 
> create l2   2 , 5 , 8 , 10 , 12 , 0 ,
> 
> 
> 
> : lists-compare
> 
>         l1 l2
> 
>         begin   over @ 0<> over @ 0<> and
> 
>         while   over @ over @ =
> 
>                 if      dup @ .
> 
>                 then
> 
>                 cell+ swap cell+ swap
> 
>         repeat
> 
>         2drop
> 
> ;
> 
> 
> 
> lists-compare
> 
> 5 12 ok
> 
> 
> 
> -- 
> 
> Coos
> 
> 
> 
> CHForth, 16 bit DOS applications
> 
> http://home.hccnet.nl/j.j.haak/forth.html

Hi WJ and all,

Simplifying the problem for the given example by changing the format of 
the lists, moving some run-time operations to compile-time, and 
some compile-time operations to edit-time gives :

\ lists-compare.f
\          #    data
create list1  5 c,  3 c, 5 c, 7 c,  8 c, 12 , 
create list2  5 c,  2 c, 5 c, 8 c, 10 c, 12 , 

: lists-compare ( -- ) 
   list1 count 1+ 1 ?do  
      list1 i + c@  list2 i + c@ = if  list1 i + c@ .  then  
   loop drop
;

lists-compare 5 12

WJ - I hope my lines are short enough for your reader...

Best regards,
Howerd

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


#25729

FromVoidVolker <voidvolker@gmail.com>
Date2013-09-17 11:06 -0700
Message-ID<516e7e8b-40f3-4b00-82a5-2b79f7913376@googlegroups.com>
In reply to#25719
Coos Haak, Alex McDonald, Howerd
> create l1   3 , 5 , 7 , 8 , 12 , 0 , 
> create l2   2 , 5 , 8 , 10 , 12 , 0 ,
But it not a lists - it is static arrays =)

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


#25730

FromAlex McDonald <blog@rivadpm.com>
Date2013-09-17 12:13 -0700
Message-ID<a88657e6-8ad4-4682-a18e-6f19db3f445c@googlegroups.com>
In reply to#25729
On Tuesday, 17 September 2013 19:06:08 UTC+1, VoidVolker  wrote:
> Coos Haak, Alex McDonald, Howerd
> 
> > create l1   3 , 5 , 7 , 8 , 12 , 0 , 
> > create l2   2 , 5 , 8 , 10 , 12 , 0 ,
> 
> But it not a lists - it is static arrays =)

All of WJ's stuff consists of a "problem", a "solution" in language X and a challenge to do it in Forth. It doesn't matter if it's a list, an array or whatever really, since no-one in their right mind would consider the code WJ posts particularly challenging as a language exercise. He's more interested in employing fancy functions from libraries as a demonstration that he can do in one line what takes other languages 10s of lines or more. 

He's also more than a little anal about line lengths. No doubt he has a snippet in Scala or Ruby that corrects line lengths and inserts the text "I've corrected ..." and "Forth is a toy..."

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


#25745

FromVoidVolker <voidvolker@gmail.com>
Date2013-09-17 22:42 -0700
Message-ID<97e209cc-2924-4063-ab06-a96818d6a963@googlegroups.com>
In reply to#25730
вторник, 17 сентября 2013 г., 23:13:18 UTC+4 пользователь Alex McDonald написал:
> On Tuesday, 17 September 2013 19:06:08 UTC+1, VoidVolker  wrote:
> 
> > Coos Haak, Alex McDonald, Howerd
> > 
> > > create l1   3 , 5 , 7 , 8 , 12 , 0 , 
> > > create l2   2 , 5 , 8 , 10 , 12 , 0 , 
> > But it not a lists - it is static arrays =)
> 
> All of WJ's stuff consists of a "problem", a "solution" in language X and a challenge to do it in Forth. It doesn't matter if it's a list, an array or whatever really, since no-one in their right mind would consider the code WJ posts particularly challenging as a language exercise. He's more interested in employing fancy functions from libraries as a demonstration that he can do in one line what takes other languages 10s of lines or more. 
> 
> 
> He's also more than a little anal about line lengths. No doubt he has a snippet in Scala or Ruby that corrects line lengths and inserts the text "I've corrected ..." and "Forth is a toy..."

Aaa, okk. I saw 'list' and think about lists =) But, in this case, if all data is available in compilation time, then we just can do standard forth optimization of task:
    .( 5 12)
And all.

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


#25749

Frommhx@iae.nl
Date2013-09-18 00:00 -0700
Message-ID<c3a76638-84f9-4b8d-8773-d9bf4a21d03a@googlegroups.com>
In reply to#25745
On Wednesday, September 18, 2013 7:42:46 AM UTC+2, VoidVolker wrote:
> вторник, 17 сентября 2013 г., 23:13:18 UTC+4 пользователь 
[..]
> Aaa, okk. I saw 'list' and think about lists =) But, in this case, 
> if all data is available in compilation time, then we just can do 
> standard forth optimization of task:
> 
>     .( 5 12)

Shorter: wait until somebody else posts the solution.

-marcel

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


#25732

FromHowerd <howerdo@yahoo.co.uk>
Date2013-09-17 13:26 -0700
Message-ID<f3d5171b-d4f6-4cf3-9a53-ce26e40336f2@googlegroups.com>
In reply to#25729
On Tuesday, September 17, 2013 7:06:08 PM UTC+1, VoidVolker wrote:
> Coos Haak, Alex McDonald, Howerd
> 
> > create l1   3 , 5 , 7 , 8 , 12 , 0 , 
> 
> > create l2   2 , 5 , 8 , 10 , 12 , 0 ,
> 
> But it not a lists - it is static arrays =)

Hi,

They are static lists of chars - or is there some special meaning of "list" that I should know about?

Best regards,
Howerd

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


#25760

FromDoug Hoffman <glidedog@gmail.com>
Date2013-09-18 08:42 -0400
Message-ID<52399faa$0$294$14726298@news.sunsite.dk>
In reply to#25729
On 9/17/13 2:06 PM, VoidVolker wrote:
>> create l1   3 , 5 , 7 , 8 , 12 , 0 ,
> But it not a lists - it is static arrays =)

You are right.  But it isn't hard to do something like what the OP did 
using a list package in Forth, as you have shown.  Actually the OP code 
errors ugly on lists that are not the same size and simply errors when 
they contain data other than integers:

OCaml:
    (combine [3;5;7;8;12] [2;5;8;10]));;
Exception: Invalid_argument "List.combine".

    (combine [3;5.5;7;8;12] [2;5.5;8;10;12]));;
Error: This expression has type float but an expression
was expected of type int

But he provided no specifications for the problem nor did he show the 
internals of his combine function.  I would have done it differently in 
Forth needing only minor modification to already written list library code:

: combine { x y  -- z }
   x size: y size: <> abort" unequal size lists"
   heap> object-list2  \ list z
   begin
     x each:
   while
     y each: drop
     over =: if over addObj: else drop then
   repeat  ;

o{ 3 5 7 8 12 } o{ 2 5 8 10 12 } combine p:
o{ 5 12 } ok

o{ 3 5.5e 7 8 12 } o{ 2 5.5e 8 10 12 } combine p:
o{ 5.5 12 } ok

o{ 'frog' 'cat' 'dog' 2 3 } o{ 'cow' 'cat' 'fish' 2 4 } combine p:
o{ 'cat' 2 } ok

Using more generalized library code is, I gather, a bit antithetical to 
what some believe is the Forth way.  However easily leveraging 
previously written code is useful in my work.

Using a list terminator like 0 means the list cannot contain 0 as an 
element.  A better list will maintain its size.  Also, it seems more 
useful to return a list that can be subsequently used if desired. 
Lastly there is the issue of discarding allocated memory used for 
anonymous lists.  If using GC then no problem, otherwise it is trivial 
to explicitly FREE.

-Doug

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


#25741

From"Ed" <invalid@invalid.com>
Date2013-09-18 14:22 +1000
Message-ID<l1b9kh$5ua$1@speranza.aioe.org>
In reply to#25719
WJ wrote:
> ...
> Since every gavino "knows" that Forth amplifies programmer productivity,
> let's see several Forth solutions that are more concise than the
> OCaml ones.

Forth is a toolkit.  It assumes the programmer can develop his own solutions
without relying on the language or someone's library to provide them.
'Productivity' accrues from being able to develop and debug routines quickly.
'Efficiency' accrues from picking the best solution for the job at hand.
Can you do that if the language/compiler is making all the decisions for you?

I like the fact that low-level Forth code isn't 'concise'.  Like assembler, it says
what it does.  That way I can determine what is more efficient.

One needs a reason to use Forth.  For me, it's the flexibility it offers.  And if I
don't like something in my compiler or want to add to it, I always can.  I don't
need to rely on anyone.


[toc] | [prev] | [standalone]


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


csiph-web