Rocksolid Light

Welcome to Rocksolid Light

mail  files  register  newsreader  groups  login

Message-ID:  

No problem is insoluble. -- Dr. Janet Wallace, "The Deadly Years", stardate 3479.4


devel / comp.lang.forth / Re: Jensen's Device

SubjectAuthor
* Jensen's DeviceAnton Ertl
+- Re: Jensen's Deviceminforth
+- Re: Jensen's DeviceAnton Ertl
`- Re: Jensen's DeviceAnton Ertl

1
Jensen's Device

<2024Mar16.094408@mips.complang.tuwien.ac.at>

  copy mid

https://news.novabbs.org/devel/article-flat.php?id=26416&group=comp.lang.forth#26416

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: anton@mips.complang.tuwien.ac.at (Anton Ertl)
Newsgroups: comp.lang.forth
Subject: Jensen's Device
Date: Sat, 16 Mar 2024 08:44:08 GMT
Organization: Institut fuer Computersprachen, Technische Universitaet Wien
Lines: 121
Message-ID: <2024Mar16.094408@mips.complang.tuwien.ac.at>
Injection-Info: dont-email.me; posting-host="1e4546c9436f3adc0dc2c02d4b8e0763";
logging-data="2998007"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18Q/JXPYET0deP9/jLBYGW1"
Cancel-Lock: sha1:8ctmiaMu8aeHgGghviOD7RSBRXQ=
X-newsreader: xrn 10.11
 by: Anton Ertl - Sat, 16 Mar 2024 08:44 UTC

Jensen's device <https://en.wikipedia.org/wiki/Jensen%27s_device>
demonstrates capabilities of Algol 60's call-by-name that later
programming languages have provided through other means.
<https://rosettacode.org/wiki/Jensen's_Device> shows solutions for
many other programming languages, including Forth.

The rosettacode task includes just one call to sum:

sum (i, 1, 100, 1/i)

This makes it easy to implement something that is not as general as
the Algol 60 version. This is shown particularly by the first Forth
version <https://rosettacode.org/wiki/Jensen's_Device#Forth>:

: sum 0 s>f 1+ swap ?do i over execute f+ loop drop ;
:noname s>f 1 s>f fswap f/ ; 1 100 sum f.

It passes i on the stack. How would one use this SUM for the
following call given by wikipedia:

Sum(i, l, m, Sum(j, l, n, A[i,j]))

The second Forth version is as follows:

fvariable ii \ i is a Forth word that we need
: sum ( xt1 lo hi xt2 -- r )
0e swap 1+ rot ?do ( addr xt r1 )
i s>f over execute f! dup execute f+
loop 2drop ;
' ii 1 100 :noname 1e ii f@ f/ ; sum f.

This is in many respects very close to the Algol version. II is a
global variable, but given the way that the first parameter of SUM is
used (just as a memory location for storing and accessing the loop
index), that does not pose problems; the use of a global variable
eliminates the need to deal with scoping.

II is also an FP variable (the Algol 60 version uses integer), but one
could just as well use a cell instead:

variable ii \ i is a Forth word that we need
: sum ( xt1 lo hi xt2 -- r )
0e swap 1+ rot ?do ( r1 xt1 xt2 )
i 2 pick execute ! dup execute f+
loop 2drop ;
' ii 1 100 :noname 1e ii @ s>f f/ ; sum f.

I have written a version using Gforth (development) features to allow
using local storage (where the memory for II/I1 is reclaimed at the
end of MAIN):

: sum {: xt: i1 lo hi xt: term -- r :}
\ stack effects: i1 ( -- addr ); term ( -- r1 )
0e hi 1+ lo +do
i i1 ! term f+
loop ;

: main ( -- )
0 {: w^ i1 :} i1 [n:l ;] 1 100 i1 [n:l @ s>f 1/f ;] sum f. ;

main

The SUM code does exactly the same things as in the second Forth
version above, but the implementation uses locals, including
defer-flavoured locals I1 and TERM (indicated by the XT: before the
local definition). I think the resulting code is easier to follow,
but I am sure others will disagree.

The more insteresting part is in MAIN. Here we create a
variable-flavoured local I1 (alternatively, one could create a
cell-sized buffer) as a replacement for the global II. To bind I1 in
the xts passed to SUM, this code uses pure-stack closures: The stack
effects involved are:

( addr ) [n:l ( addr ) ;] ( xt < -- addr > )
( addr ) [n:l ( addr ) @ s>f 1/f ( r ) ;] ( xt < -- r > )

So these pure-stack closures take the I1 address from the data stack
at closure construction time and push it on the data stack at closure
execution time. The N in [N:L indicates that one cell is involved,
the L indicates that the memory for the closure has the lifetime of
locals (in this case until the end of MAIN).

The C entry points out that macros are close to call-by-name
semantics. Let's see how that works out in Gforth:

: ]sum ( compile-time: ) {: xt: i1 xt: term -- :}
\ run-time: ( lo hi -- r )
] ]] 0e 1+ swap +do
i i1 ! term f+
loop [[ ; immediate

variable i1
: term1 i1 @ s>f 1/f ;
: main2 ( -- )
[ ' i1 ] 1 100 [ ' term1 ]sum f. ;

main2 cr

Here main2 is decompiled as:

: main2 #1 #100
0.00000000000000E0 1+ swap
+do i i1 ! term1 f+
loop
f. ; ok

This variant reverts to using a global variable I1, because the macro
is expanded at compile-time and dealing with run-time locals in macros
is an unsolved problem in Gforth. It uses a named definition TERM1
rather than a quotation for better readability of the decompiler
output. The code of the macro is remarkably similar to the code of
the Gforth SUM above, thanks to ]] ... [[, and also the way
POSTPONE/]] treats defer-flavoured locals (it COMPILE,s them).

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: https://forth-standard.org/
EuroForth 2023: https://euro.theforth.net/2023

Re: Jensen's Device

<dab8d821f80353f67aedefd052a6b631@www.novabbs.com>

  copy mid

https://news.novabbs.org/devel/article-flat.php?id=26419&group=comp.lang.forth#26419

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!.POSTED!not-for-mail
From: minforth@gmx.net (minforth)
Newsgroups: comp.lang.forth
Subject: Re: Jensen's Device
Date: Sat, 16 Mar 2024 22:12:11 +0000
Organization: novaBBS
Message-ID: <dab8d821f80353f67aedefd052a6b631@www.novabbs.com>
References: <2024Mar16.094408@mips.complang.tuwien.ac.at>
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 8bit
Injection-Info: i2pn2.org;
logging-data="2233172"; mail-complaints-to="usenet@i2pn2.org";
posting-account="t+lO0yBNO1zGxasPvGSZV1BRu71QKx+JE37DnW+83jQ";
User-Agent: Rocksolid Light
X-Rslight-Site: $2y$10$7GUvs5fcfKb4L/UJ8otsM.8C/zfmXMQx11A2KDv5O0rPc0L0/wn/.
X-Spam-Checker-Version: SpamAssassin 4.0.0
X-Rslight-Posting-User: d2a19558f194e2f1f8393b8d9be9ef51734a4da3
 by: minforth - Sat, 16 Mar 2024 22:12 UTC

.. can't remember who called Forth a write-only language .. ;-)

btw impressive examples!

Re: Jensen's Device

<2024Mar17.093928@mips.complang.tuwien.ac.at>

  copy mid

https://news.novabbs.org/devel/article-flat.php?id=26422&group=comp.lang.forth#26422

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: anton@mips.complang.tuwien.ac.at (Anton Ertl)
Newsgroups: comp.lang.forth
Subject: Re: Jensen's Device
Date: Sun, 17 Mar 2024 08:39:28 GMT
Organization: Institut fuer Computersprachen, Technische Universitaet Wien
Lines: 43
Message-ID: <2024Mar17.093928@mips.complang.tuwien.ac.at>
References: <2024Mar16.094408@mips.complang.tuwien.ac.at>
Injection-Info: dont-email.me; posting-host="4e038d4e32f6cb3299db8b0101aed01e";
logging-data="3609768"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1912vAEG0z+9HswS+3Uxr2S"
Cancel-Lock: sha1:/0ZynhggeS5xliQTrigPTMFFNUA=
X-newsreader: xrn 10.11
 by: Anton Ertl - Sun, 17 Mar 2024 08:39 UTC

anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
>Jensen's device <https://en.wikipedia.org/wiki/Jensen%27s_device>
>demonstrates capabilities of Algol 60's call-by-name that later
>programming languages have provided through other means.
><https://rosettacode.org/wiki/Jensen's_Device> shows solutions for
>many other programming languages, including Forth.
>
>The rosettacode task includes just one call to sum:
>
>sum (i, 1, 100, 1/i)
>
>This makes it easy to implement something that is not as general as
>the Algol 60 version. This is shown particularly by the first Forth
>version <https://rosettacode.org/wiki/Jensen's_Device#Forth>:
>
>: sum 0 s>f 1+ swap ?do i over execute f+ loop drop ;
>:noname s>f 1 s>f fswap f/ ; 1 100 sum f.
>
>It passes i on the stack. How would one use this SUM for the
>following call given by wikipedia:
>
>Sum(i, l, m, Sum(j, l, n, A[i,j]))
>
>The second Forth version is as follows:
>
>fvariable ii \ i is a Forth word that we need
>: sum ( xt1 lo hi xt2 -- r )
> 0e swap 1+ rot ?do ( addr xt r1 )
> i s>f over execute f! dup execute f+
> loop 2drop ;
>' ii 1 100 :noname 1e ii f@ f/ ; sum f.

Looking at the history page, I find that the second version is by me,
written 10 years ago, and discussed here
<2014Feb14.124846@mips.complang.tuwien.ac.at> ff., and that the first
version is by Hans Bezemer.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: https://forth-standard.org/
EuroForth 2023: https://euro.theforth.net/2023

Re: Jensen's Device

<2024Mar17.095917@mips.complang.tuwien.ac.at>

  copy mid

https://news.novabbs.org/devel/article-flat.php?id=26423&group=comp.lang.forth#26423

  copy link   Newsgroups: comp.lang.forth
Path: i2pn2.org!i2pn.org!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: anton@mips.complang.tuwien.ac.at (Anton Ertl)
Newsgroups: comp.lang.forth
Subject: Re: Jensen's Device
Date: Sun, 17 Mar 2024 08:59:17 GMT
Organization: Institut fuer Computersprachen, Technische Universitaet Wien
Lines: 78
Message-ID: <2024Mar17.095917@mips.complang.tuwien.ac.at>
References: <2024Mar16.094408@mips.complang.tuwien.ac.at>
Injection-Info: dont-email.me; posting-host="4e038d4e32f6cb3299db8b0101aed01e";
logging-data="3633127"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX193Vx9b/rlpkw6v7vracBox"
Cancel-Lock: sha1:ldv2BWPPOi2XAZB1/NnCCxdXdxU=
X-newsreader: xrn 10.11
 by: Anton Ertl - Sun, 17 Mar 2024 08:59 UTC

anton@mips.complang.tuwien.ac.at (Anton Ertl) writes:
>The C entry points out that macros are close to call-by-name
>semantics. Let's see how that works out in Gforth:
>
>: ]sum ( compile-time: ) {: xt: i1 xt: term -- :}
> \ run-time: ( lo hi -- r )
> ] ]] 0e 1+ swap +do
> i i1 ! term f+
> loop [[ ; immediate
>
>variable i1
>: term1 i1 @ s>f 1/f ;
>: main2 ( -- )
> [ ' i1 ] 1 100 [ ' term1 ]sum f. ;
>
>main2 cr
>
>Here main2 is decompiled as:
>
>: main2 #1 #100
> 0.00000000000000E0 1+ swap
> +do i i1 ! term1 f+
> loop
> f. ; ok
>
>This variant reverts to using a global variable I1, because the macro
>is expanded at compile-time and dealing with run-time locals in macros
>is an unsolved problem in Gforth. It uses a named definition TERM1
>rather than a quotation for better readability of the decompiler
>output. The code of the macro is remarkably similar to the code of
>the Gforth SUM above, thanks to ]] ... [[, and also the way
>POSTPONE/]] treats defer-flavoured locals (it COMPILE,s them).

A more idiomatic macro-based approach is as follows:

: sum< ( run-time: hi+1 lo -- 0e )
0e postpone ?do ; immediate

: >sum ( run-time: r1 r2 -- r3 )
postpone f+ postpone loop ; immediate

: main3 ( -- )
101 1 sum< 1e i s>f f/ >sum f. ;
main3 cr

Here SUM is split into two parts, and the TERM parameter is included
as compiled code between these two parts, satisfying call-by-name's
intent of textual replacement semantics.

The parameter i in the Algol 60 variant is an artifact of Algol 60's
way of working with variables; you also have to provide it to the for
loop in Algol 60 and, e.g., Pascal. Forth produces the loop index of
the inner counted loop with I, and so does SUM<...>SUM; an alternative
would have been to provide the loop index on the data stack.

The loop bounds are provided in the Forth-idiomatic form with the
limit (hi+1) given first and not being included.

The solution can be written slightly shorter using ]]...[[, but I
decided to stick to Forth-2012 here.

The Wikipedia page gives Sum(i, l, m, Sum(j, l, n, A[i,j])) as another
usage example; this would become:

: main4 ( -- r )
m 1+ l sum< n 1+ l sum< A{{ j i }} f@ >sum >sum ;

Here I used the FSL array syntax. One notable difference from the
Algol code is that the outer loop index is J, while Algol uses the
variable given (in this case i). That's the same as for other counted
loops in Forth.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: https://forth-standard.org/
EuroForth 2023: https://euro.theforth.net/2023

1
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor