• What use are closures Re: Closures in kForth

    From none) (albert@21:1/5 to no.email@nospam.invalid on Mon Oct 24 15:14:15 2022
    In article <87zgdmdqbe.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    Krishna Myneni <krishna.myneni@ccreweb.org> writes:
    I'm not sure why you say that we cannot implement them in their "pure
    meaning." Do you mean because we are not dealing with purely symbolic
    expressions?

    The methods you gave seem to allocate storage for the saved locals in
    the dictionary, with no way to reclaim the storage once you are done
    with the closure. That's not so great if you program in a style that
    creates a lot of closures on the fly. I don't know if there are other
    issues besides that. Languages that promote using lots of closures
    usually reclaim the storage by garbage collection. Idk if there are
    other good ways to do it. Or if you're only making a few closures, it
    is probably ok to just retain their storage permanently.

    I find it hard to imagine a situation -- programming problem --
    where you need a lot of closures. And indeed a few closures is
    easy enough.
    I'm prepared to be convinced to think about adding any feature
    that makes life easier. So convince me.

    Groetjes Albert
    --
    "in our communism country Viet Nam, people are forced to be
    alive and in the western country like US, people are free to
    die from Covid 19 lol" duc ha
    albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to albert@cherry. on Mon Oct 24 11:28:43 2022
    albert@cherry.(none) (albert) writes:
    I find it hard to imagine a situation -- programming problem --
    where you need a lot of closures. And indeed a few closures is
    easy enough.

    Rather than concoct an example specifically made for that purpose, here
    is a practical problem given as part of a productivity experiment, where
    the most compact solution (Haskell) used closures to represent geometric regions, making it easy to represent unions and intersections of regions
    by making more closures:

    https://web.cecs.pdx.edu/~apt/cs457_2005/hudak-jones.pdf

    See page 5 for the problem description.

    I'm prepared to be convinced to think about adding any feature
    that makes life easier. So convince me.

    I think that style doesn't make much sense in Forth, especially without
    garbage collection. Does the style make life easier? I think so. Is
    it necessary or important? I would say you could do the same thing in
    other ways, though with less convenience.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ruvim@21:1/5 to Krishna Myneni on Fri Oct 28 11:49:44 2022
    On 2022-10-23 21:52, Krishna Myneni wrote:
    [...]

    Forth closures of the type implemented by Anton and Ruvim are found to
    be quite useful when we need to generate an anonymous definition at
    runtime, which binds runtime-computed values.

    Ruvim's original definition of PARTIAL1 is state-dependent, i.e. it
    contains an expression of the sort, "STATE @ IF ... THEN." On a dual-semantics system it is possible to define PARTIAL1 without any
    reference to STATE as follows (in Gforth):

    : partial1 ( x xt1 -- xt2 )
        2>r :noname r> r> ( -- xt1 x )
        postpone literal
        compile,
        postpone ;
    ;
    compsem:
        ['] partial1 compile,
        ]
    ;

    Don't want to upset you, but it does not work correctly in Gforth.

    This example shows that via "set-compsem" you don't merely define
    compilation semantics for a word, but (despite of the name) you specify
    a definition that can demonstrate behavior that is not a part of the compilation semantics.

    Namely, if you perform this definition in interpretation state, the
    result can vary from the compilation semantics for the word.

    In this particular case, when this definition (which was created by
    "compsem:") is performed:
    - if the system in compilation state, its behavior is to append
    "partial1" to the current definition.
    - if the system in interpretation state, its behavior is to append "partial1" to the current definition *and* enters compilation state.

    Only the first behavior variant is the compilation semantics for
    "partial1" (in the normative notion).
    There are no conditions when the second behavior variant can be
    demonstrated by the Forth text interpreter when it encounters the word
    name "partial1", so it is neither the compilation semantics, nor
    interpretation semantics for "partial1".


    Moreover, in Gforth, when you execute the xt that "name>compile"
    returns, you are not guaranteed that the compilation semantics (i.e.,
    the first behavior variant from above in the case of "partial1") will be performed regardless of the STATE.


    A test case:

    : p1 [ s" partial1" find-name name>compile execute 123 . ] ;

    \ the code in the square brackets should append
    \ the execution semantics of "partial1" to "p1",
    \ and then print "123".

    \ In Gforth it prints nothing.

    456 ' . p1 \ It should print nothing and leave xt on the stack.
    \ In Gforth it prints "123", leaves xt and enters compilation state.

    execute \ It should print "456".
    \ In Gforth it prints nothing and
    \ tries to append "execute" to the current definition
    \ (due to compilation state)


    NB: your code doesn't violate the current specifications for
    "set-compsem" and "name>compile".

    The implementation of "name>compile" in Gforth just effectively imposes
    a restriction on programs — a program should perform xt from
    "name>compile" only in compilation state to perform the corresponding compilation semantics (in the general case). This restriction is
    similar to one that the popular implementation for "postpone" imposes.


    And, as you can see, the dual-xt approach has not allowed to avoid this problem.



    [...]

    --
    Ruvim

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Krishna Myneni@21:1/5 to Ruvim on Fri Oct 28 09:21:09 2022
    On 10/28/22 06:49, Ruvim wrote:
    On 2022-10-23 21:52, Krishna Myneni wrote:
    [...]

    Forth closures of the type implemented by Anton and Ruvim are found to
    be quite useful when we need to generate an anonymous definition at
    runtime, which binds runtime-computed values.

    Ruvim's original definition of PARTIAL1 is state-dependent, i.e. it
    contains an expression of the sort, "STATE @ IF ... THEN." On a
    dual-semantics system it is possible to define PARTIAL1 without any
    reference to STATE as follows (in Gforth):

    : partial1 ( x xt1 -- xt2 )
         2>r :noname r> r> ( -- xt1 x )
         postpone literal
         compile,
         postpone ;
    ;
    compsem:
         ['] partial1 compile,
         ]
    ;

    Don't want to upset you, but it does not work correctly in Gforth.


    Yes, there is something wrong with the definition. It is not a problem
    with Gforth or a problem with NAME>COMPILE.

    ..
    Moreover, in Gforth, when you execute the xt that "name>compile"
    returns, you are not guaranteed that the compilation semantics (i.e.,
    the first behavior variant from above in the case of "partial1") will be performed regardless of the STATE.


    Yes, Gforth is executing the specified compilation semantics of PARTIAL1
    in interpretation state for your example below. Note that the
    compilation semantics I specified with COMPSEM: includes a return to compilation state.


    A test case:

      : p1 [ s" partial1" find-name name>compile execute  123 . ] ;

      \ the code in the square brackets should append
      \ the execution semantics of "partial1" to "p1",
      \ and then print "123".
    ...

    If we look at the compiled definition for P1 in Gforth it shows the
    following:

    see p1
    : p1
    [COMPILE] partial1 #123 . ] ; ok

    This shows that NAME>COMPILE is indeed doing what it should do. It is performing the compilation semantics regardless of STATE -- it is just
    not the behavior needed for your test case.



    NB: your code doesn't violate the current specifications for
    "set-compsem" and "name>compile".

    The implementation of "name>compile" in Gforth just effectively imposes
    a restriction on programs — a program should perform xt from
    "name>compile" only in compilation state to perform the corresponding compilation semantics (in the general case).

    Yes, it appears that this is the case for the example shown.

      This restriction is
    similar to one that the popular implementation for "postpone" imposes.



    And, as you can see, the dual-xt approach has not allowed to avoid this problem.


    Not with my example. Is it a fundamental limitation or is my definition
    of PARTIAL1 just not the compatible one? I'm not sure.

    --
    Krishna

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Krishna Myneni@21:1/5 to Krishna Myneni on Fri Oct 28 10:17:44 2022
    On 10/28/22 09:21, Krishna Myneni wrote:
    On 10/28/22 06:49, Ruvim wrote:
    On 2022-10-23 21:52, Krishna Myneni wrote:
    ..

    : partial1 ( x xt1 -- xt2 )
         2>r :noname r> r> ( -- xt1 x )
         postpone literal
         compile,
         postpone ;
    ;
    compsem:
         ['] partial1 compile,
         ]
    ;

    ... but it does not work correctly in Gforth.


    Yes, there is something wrong with the definition. It is not a problem
    with Gforth or a problem with NAME>COMPILE.

    ...


    A test case:

       : p1 [ s" partial1" find-name name>compile execute  123 . ] ;

       \ the code in the square brackets should append
       \ the execution semantics of "partial1" to "p1",
       \ and then print "123".
    ...

    If we look at the compiled definition for P1 in Gforth it shows the following:

    see p1
    : p1
      [COMPILE] partial1 #123 . ] ; ok

    This shows that NAME>COMPILE is indeed doing what it should do. It is performing the compilation semantics regardless of STATE -- it is just
    not the behavior needed for your test case.

    ..

    The lesson I take away from your example is that dual-semantics words
    should not change the STATE except that compilation semantics may
    include a sequence such as "[ ... ]". In my dual-semantics definition of PARTIAL1 the compilation semantics includes "]" -- state is explicitly
    being changed back to .

    The following dual-semantics definition does work with your test case
    and also with the original test cases:


    : partial1 ( x xt1 -- xt2 )
    2>r :noname r> r> ( -- xt1 x )
    postpone literal
    compile,
    postpone ;
    ;
    compsem: [ ' partial1 ] literal compile, ;


    : p1 [ s" partial1" find-name name>compile execute 123 . ] ; 123 ok
    see p1
    : p1
    [COMPILE] partial1 ; ok

    : n^2+ [: dup * + ;] partial1 ; ok
    5 n^2+ constant 5^2+ ok
    6 5^2+ execute . 31 ok

    It thus appears that a correct dual-semantics definition can solve the
    problem.

    --
    Krishna

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ruvim@21:1/5 to Krishna Myneni on Fri Oct 28 15:30:05 2022
    On 2022-10-28 14:21, Krishna Myneni wrote:
    On 10/28/22 06:49, Ruvim wrote:
    [...]

    Moreover, in Gforth, when you execute the xt that "name>compile"
    returns, you are not guaranteed that the compilation semantics (i.e.,
    the first behavior variant from above in the case of "partial1") will
    be performed regardless of the STATE.


    Yes, Gforth is executing the specified compilation semantics of PARTIAL1
    in interpretation state for your example below. Note that the
    compilation semantics I specified with COMPSEM: includes a return to compilation state.


    "Enter compilation state" cannot be a part of compilation semantics at all.

    "compsem:" allows you to specify a definition that can demonstrate
    behavior that cannot be a part of any compilation semantics in principle.



    A test case:

       : p1 [ s" partial1" find-name name>compile execute  123 . ] ;

       \ the code in the square brackets should append
       \ the execution semantics of "partial1" to "p1",
       \ and then print "123".
    ...

    If we look at the compiled definition for P1 in Gforth it shows the following:

    see p1
    : p1
      [COMPILE] partial1 #123 . ] ; ok

    This shows that NAME>COMPILE is indeed doing what it should do. It is performing the compilation semantics regardless of STATE -- it is just
    not the behavior needed for your test case.

    Let's try to perform the returned xt in compilation state:

    : ]execute[ ( i*x xt -- j*x ) ] execute postpone [ ; immediate
    : p1 [ s" partial1" find-name name>compile ]execute[ 123 . ] ;
    see p1

    | : p1
    | [COMPILE] partial1 ;

    The result is different. It means, the behavior of the returned xt
    depends on STATE.





    NB: your code doesn't violate the current specifications for
    "set-compsem" and "name>compile".

    The implementation of "name>compile" in Gforth just effectively
    imposes a restriction on programs — a program should perform xt from
    "name>compile" only in compilation state to perform the corresponding
    compilation semantics (in the general case).

    Yes, it appears that this is the case for the example shown.

      This restriction is similar to one that the popular implementation
    for "postpone" imposes.



    And, as you can see, the dual-xt approach has not allowed to avoid
    this problem.


    Not with my example. Is it a fundamental limitation or is my definition
    of PARTIAL1 just not the compatible one? I'm not sure.

    I don't see any incompatibility with "compsem:" or "name>compile".


    But, the specification for "compsem:" can confuse:

    | Changes the compilation semantics of the current definition to
    | perform the definition starting at the "compsem:"

    "To perform" does not mean that the compilation semantics are identical
    to the execution semantics of the definition starting at the "compsem:".

    Apart from a not normative notion of "compilation semantics", of course.


    A more tidy wording:
    Make the compilation semantics of the most recent definition to perform
    in compilation state the execution semantics of the definition starting
    at the "compsem:".

    Or even this:
    Make the compilation semantics of the most recent definition to be
    equivalent to perform in compilation state the execution semantics of
    the definition starting at the "compsem:".



    --
    Ruvim

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Krishna Myneni@21:1/5 to All on Fri Oct 28 11:39:59 2022
    On 10/28/22 10:30, Ruvim wrote:


    The problem stems from your original definition of PARTIAL1 :

    : partial1 ( x xt1 -- xt2 )
    \ create a partially applied definition xt2
    \ by fixing the top argument for xt1
    state @ >r
    2>r :noname r> r> lit, compile, postpone ;
    r> if ] then
    ;

    There was no need for you to bring STATE into this definition. The
    following works just as well for all subsequent definitions using
    PARTIAL1, including your closures.

    : partial1 ( x xt1 -- xt2 )
    2>r :noname r> r> postpone literal compile, postpone ;
    ; ok


    : foo [: dup * + ;] partial1 ; ok
    2 foo constant f2 ok
    3 foo constant f3 ok
    0 f2 execute . 4 ok
    1 f2 execute . 5 ok
    0 f3 execute . 9 ok
    1 f3 execute . 10 ok
    2 f3 execute . 11 ok

    : cl[n:d postpone [: ; immediate ok
    : ]cl postpone ;] postpone partial1 ; immediate ok
    : n^2+ cl[n:d dup * + ]cl ; ok
    2 n^2+ constant f2


    : p1 [ s" partial1" find-name name>compile execute 123 . ] ; 123 ok
    see p1
    : p1
    partial1 ; ok

    --
    Krishna

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Krishna Myneni@21:1/5 to Krishna Myneni on Fri Oct 28 18:16:17 2022
    On 10/28/22 11:39, Krishna Myneni wrote:
    On 10/28/22 10:30, Ruvim wrote:


    The problem stems from your original definition of PARTIAL1 :

      : partial1 ( x xt1 -- xt2 )
        \ create a partially applied definition xt2
        \ by fixing the top argument for xt1
        state @ >r
        2>r :noname r> r> lit, compile, postpone ;
        r> if ] then
      ;

    There was no need for you to bring STATE into this definition. The
    following works just as well for all subsequent definitions using
    PARTIAL1, including your closures.

    : partial1 ( x xt1 -- xt2 )
        2>r :noname r> r> postpone literal compile, postpone ;
    ;  ok

    ..

    This was a useful exercise. It allowed me to fix an issue in kForth,
    which didn't allow me to use COMPILE-NAME (or equivalently,
    "NAME>COMPILE EXECUTE") in interpretation state, following Ruvim's test.
    The latest update to kForth-64 on Github fixes this issue.

    Update for kForth-32 to follow soon.

    --
    Krishna

    ----
    include ans-words

    /home/krishna/kforth/ans-words.4th
    ok
    include ssd

    /home/krishna/kforth/ssd.4th

    /home/krishna/kforth/struct-200x.4th

    /home/krishna/kforth/modules.4th

    /home/krishna/kforth/dump.4th
    ok
    : partial1 ( x xt1 -- xt2 )
    2>r :noname r> r> postpone literal compile, postpone ;
    ;
    ok
    : foo [: dup * + ;] partial1 ;
    ok
    2 foo constant f2
    ok
    3 foo constant f3
    ok
    0 f2 execute .
    4 ok
    1 f2 execute .
    5 ok
    0 f3 execute .
    9 ok
    1 f3 execute .
    10 ok
    2 f3 execute .
    11 ok
    : cl[n:d postpone [: ; immediate
    ok
    : ]cl postpone ;] postpone partial1 ; immediate
    ok
    : n^2+ cl[n:d dup * + ]cl ;
    ok
    2 n^2+ constant f2
    ok
    3 n^2+ constant f3
    ok
    0 f2 execute .
    4 ok
    1 f2 execute .
    5 ok
    0 f3 execute .
    9 ok
    1 f3 execute .
    10 ok
    2 f3 execute .
    11 ok
    ok
    : p1 [ s" partial1" find-name name>compile execute 123 . ] ;
    123 ok
    see p1
    55D3E22E3240 PARTIAL1
    55D3E22E3249 RET
    ok
    -----

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ruvim@21:1/5 to Krishna Myneni on Sat Oct 29 08:19:26 2022
    On 2022-10-28 16:39, Krishna Myneni wrote:
    On 10/28/22 10:30, Ruvim wrote:
    [...]

    The problem stems from your original definition of PARTIAL1 :

      : partial1 ( x xt1 -- xt2 )
        \ create a partially applied definition xt2
        \ by fixing the top argument for xt1
        state @ >r
        2>r :noname r> r> lit, compile, postpone ;
        r> if ] then
      ;

    This my original definition does not have that problem.

    Your system is able to create new definitions during compiling of
    another definition. So I just tried to employ this feature.

    As I can see now, to make it work ":noname" should be executed in interpretation state only. The word "execute-interpretively" is intended
    for that.

    A corrected version:

    [undefined] lit, [if] : lit, ( x -- ) postpone literal ; [then]

    : compilation ( -- flag ) state @ 0<> ;
    : leave-compilation ( -- ) postpone [ ;
    : enter-compilation ( -- ) ] ;

    : execute-interpretively ( i*x xt -- j*x )
    compilation 0= if execute exit then
    leave-compilation execute enter-compilation
    ;

    : partial1 ( x xt1 -- xt2 )
    [: 2>r :noname r> r> lit, compile, postpone ; ;]
    execute-interpretively
    ;


    A test case

    : [bar] 123 ['] . partial1 compile, ; immediate

    : baz [bar] 456 . ;

    baz \ should print "123 456"


    This test will not work on some standard system, since it has an
    environmental dependency on creation definitions while compiling another definition. kForth complies to this dependency.



    NB: "partial1" is an ordinary word.

    This example also shows that the dual-xt approach cannot help us to
    avoid STATE-dependent behavior (namely, STATE-dependent execution
    semantics).





    There was no need for you to bring STATE into this definition. The
    following works just as well for all subsequent definitions using
    PARTIAL1, including your closures.

    : partial1 ( x xt1 -- xt2 )
        2>r :noname r> r> postpone literal compile, postpone ;
    ;


    It does not work in another test (see above).



    --
    Ruvim

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Krishna Myneni@21:1/5 to Ruvim on Sat Oct 29 06:28:37 2022
    On 10/29/22 03:19, Ruvim wrote:
    On 2022-10-28 16:39, Krishna Myneni wrote:

    A test case

      : [bar]  123 ['] . partial1  compile, ; immediate

      : baz [bar] 456 . ;

      baz \ should print "123 456"


    This test will not work on some standard system, since it has an environmental dependency on creation definitions while compiling another definition. kForth complies to this dependency.

    ..

    : partial1 ( x xt1 -- xt2 )
         2>r :noname r> r> postpone literal compile, postpone ;
    ;


    It does not work in another test (see above).



    The simpler definition of PARTIAL1 works fine under kForth. Your test,

    : [bar] 123 ['] . partial1 compile, ; immediate

    can be simplified to be

    : bar 123 ['] partial1 compile, ;
    : baz [ bar ] 456 . ;

    baz
    123 456 ok

    There is no need for all of the contortions of EXECUTE-INTERPRETIVELY
    and the STATE dependence of PARTIAL1 if a system allows

    : NAME ... [ :NONAME ... ; ] ... ;

    --
    Krishna

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ruvim@21:1/5 to Krishna Myneni on Sat Oct 29 12:29:55 2022
    On 2022-10-29 11:28, Krishna Myneni wrote:
    On 10/29/22 03:19, Ruvim wrote:
    On 2022-10-28 16:39, Krishna Myneni wrote:

    A test case

       : [bar]  123 ['] . partial1  compile, ; immediate

       : baz [bar] 456 . ;

       baz \ should print "123 456"


    This test will not work on some standard system, since it has an
    environmental dependency on creation definitions while compiling
    another definition. kForth complies to this dependency.

    ..

    : partial1 ( x xt1 -- xt2 )
         2>r :noname r> r> postpone literal compile, postpone ;
    ;


    It does not work in another test (see above).



    The simpler definition of PARTIAL1 works fine under kForth.

    It does not work in the above test in kForth:

    : baz [bar] 456 . ;
    Line 9: VM Error(-276): End of definition with no beginning

    But my more complex definition of "partial1" works.


    Your test,

    : [bar]  123 ['] . partial1  compile, ; immediate

    can be simplified to be

    : bar 123 ['] partial1 compile, ;
    : baz [ bar ] 456 . ;

    baz
    123 456  ok


    A test purpose is not to solve a practical task, but to check how a
    system or program behaves in some edge cases.


    The word "partial1", as it was initially defined by me, has a
    restriction in a standard program: it cannot be performed if the current definition exists (due to 3.4.5).

    It's OK if you can live with this restriction. But if a system already implements the corresponding capabilities under the hood, I would prefer
    to avoid this restriction, than document/explain it to users.


    BTW, it's possible to define "partial1" without this restriction in a standard-compliant way, but it will be significant larger and slightly
    less efficient in run-time.



    There is no need for all of the contortions of EXECUTE-INTERPRETIVELY
    and the STATE dependence of PARTIAL1 if a system allows

    : NAME ... [ :NONAME ... ; ] ... ;


    Well, it looks like you admit that the dual-xt approach does not provide
    any special means to define a more advanced "partial1".



    --
    Ruvim

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Krishna Myneni@21:1/5 to Ruvim on Sat Oct 29 11:03:52 2022
    On 10/29/22 07:29, Ruvim wrote:
    On 2022-10-29 11:28, Krishna Myneni wrote:
    On 10/29/22 03:19, Ruvim wrote:
    On 2022-10-28 16:39, Krishna Myneni wrote:

    A test case

       : [bar]  123 ['] . partial1  compile, ; immediate

       : baz [bar] 456 . ;

       baz \ should print "123 456"


    This test will not work on some standard system, since it has an
    environmental dependency on creation definitions while compiling
    another definition. kForth complies to this dependency.

    ..

    : partial1 ( x xt1 -- xt2 )
         2>r :noname r> r> postpone literal compile, postpone ;
    ;


    It does not work in another test (see above).



    The simpler definition of PARTIAL1 works fine under kForth.

    It does not work in the above test in kForth:

      : baz [bar] 456 . ;
      Line 9:  VM Error(-276): End of definition with no beginning

    But my more complex definition of "partial1" works.


    Your test,

    : [bar]  123 ['] . partial1  compile, ; immediate

    can be simplified to be

    : bar 123 ['] partial1 compile, ;
    : baz [ bar ] 456 . ;

    baz
    123 456  ok


    A test purpose is not to solve a practical task, but to check how a
    system or program behaves in some edge cases.


    The word "partial1", as it was initially defined by me, has a
    restriction in a standard program: it cannot be performed if the current definition exists (due to 3.4.5).

    It's OK if you can live with this restriction. But if a system already implements the corresponding capabilities under the hood, I would prefer
    to avoid this restriction, than document/explain it to users.


    BTW, it's possible to define "partial1" without this restriction in a standard-compliant way, but it will be significant larger and slightly
    less efficient in run-time.



    There is no need for all of the contortions of EXECUTE-INTERPRETIVELY
    and the STATE dependence of PARTIAL1 if a system allows

    : NAME ... [ :NONAME ... ; ] ... ;


    Well, it looks like you admit that the dual-xt approach does not provide
    any special means to define a more advanced "partial1".


    All I am saying is that the simple definition of PARTIAL1 which has no reference to STATE suits our purpose at hand, e.g. for closures. It does
    so regardless of whether or not a system adheres to 3.4.5 of the
    standard. The simple definition of PARTIAL1 will not pass your most
    recent test.

    I simply point out that your test of [BAR] is no drawback for systems
    which do violate 3.4.5 and allow execution of :NONAME while the
    compilation of the current definition is suspended. We can obtain the
    same effect of the test by using "[" and "]" to change states.

    While the purpose of your test is clear, the point of implementing and
    testing words is to achieve some goal(s) in the simplest and most
    consistent manner which can meet the goal(s). You are adding an
    extraordinary amount of complexity to allow for PARTIAL1 to be used in
    all possible corner cases -- this is simply not a practical approach
    because such complexity will be avoided by programmers.

    --
    Krishna

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ruvim@21:1/5 to Krishna Myneni on Wed Nov 2 19:11:39 2022
    On 2022-10-29 16:03, Krishna Myneni wrote:
    On 10/29/22 07:29, Ruvim wrote:
    [...]
    The word "partial1", as it was initially defined by me, has a
    restriction in a standard program: it cannot be performed if the
    current definition exists (due to 3.4.5).

    It's OK if you can live with this restriction. But if a system already
    implements the corresponding capabilities under the hood, I would
    prefer to avoid this restriction, than document/explain it to users.
    [...]

    There is no need for all of the contortions of EXECUTE-INTERPRETIVELY
    and the STATE dependence of PARTIAL1 if a system allows

    : NAME ... [ :NONAME ... ; ] ... ;


    Well, it looks like you admit that the dual-xt approach does not
    provide any special means to define a more advanced "partial1".


    All I am saying is that the simple definition of PARTIAL1 which has no reference to STATE suits our purpose at hand, e.g. for closures. It does
    so regardless of whether or not a system adheres to 3.4.5 of the
    standard. The simple definition of PARTIAL1 will not pass your most
    recent test.

    I simply point out that your test of [BAR] is no drawback for systems
    which do violate 3.4.5 and allow execution of :NONAME while the
    compilation of the current definition is suspended.

    Just a side note.
    The section "3.4.5" does not restrict a system, but only a program.

    During compilation of a definition, a system may use data space at it's
    own discretion.

    And if your system provides an advanced "partial1" — it does not violate "3.4.5".


    [...]

    You are adding an
    extraordinary amount of complexity to allow for PARTIAL1 to be used in
    all possible corner cases -- this is simply not a practical approach
    because such complexity will be avoided by programmers.

    I can't agree with that, but agree with Anton's formulation: "As a
    system implementor, you may be tempted to cut corners, but that means
    you also cut the corner cases, and users of your system will get
    unpleasant surprises"[1]


    [1] https://github.com/ForthHub/discussion/discussions/105#discussioncomment-3715333

    --
    Ruvim

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Krishna Myneni@21:1/5 to Ruvim on Thu Nov 3 08:03:20 2022
    On 11/2/22 14:11, Ruvim wrote:
    On 2022-10-29 16:03, Krishna Myneni wrote:
    On 10/29/22 07:29, Ruvim wrote:
    [...]
    The word "partial1", as it was initially defined by me, has a
    restriction in a standard program: it cannot be performed if the
    current definition exists (due to 3.4.5).

    It's OK if you can live with this restriction. But if a system
    already implements the corresponding capabilities under the hood, I
    would prefer to avoid this restriction, than document/explain it to
    users.
    [...]

    There is no need for all of the contortions of
    EXECUTE-INTERPRETIVELY and the STATE dependence of PARTIAL1 if a
    system allows

    : NAME ... [ :NONAME ... ; ] ... ;


    Well, it looks like you admit that the dual-xt approach does not
    provide any special means to define a more advanced "partial1".


    All I am saying is that the simple definition of PARTIAL1 which has no
    reference to STATE suits our purpose at hand, e.g. for closures. It
    does so regardless of whether or not a system adheres to 3.4.5 of the
    standard. The simple definition of PARTIAL1 will not pass your most
    recent test.

    I simply point out that your test of [BAR] is no drawback for systems
    which do violate 3.4.5 and allow execution of :NONAME while the
    compilation of the current definition is suspended.

    Just a side note.
    The section "3.4.5" does not restrict a system, but only a program.

    During compilation of a definition, a system may use data space at it's
    own discretion.

    And if your system provides an advanced "partial1" — it does not violate "3.4.5".


    I never claimed that a system in which a "first class" PARTIAL1 may be
    written will violate 3.4.5. My claim is that a system which permits a
    :NONAME definition nested within a definition can support an advanced
    PARTIAL1 -- the two are different claims.


    [...]

    You are adding an extraordinary amount of complexity to allow for
    PARTIAL1 to be used in all possible corner cases -- this is simply not
    a practical approach because such complexity will be avoided by
    programmers.

    I can't agree with that, but agree with Anton's formulation: "As a
    system implementor, you may be tempted to cut corners, but that means
    you also cut the corner cases, and users of your system will get
    unpleasant surprises"[1]


    My argument is not against writing a first class PARTIAL1 which works as expected using POSTPONE '(tick) NAME>COMPILE etc. My issue is
    understanding what may be structurally wrong with the design of a Forth
    system which makes writing a first class PARTIAL1 a complex task. Dual-semantics systems go a long way towards simplifying the definition
    of first class words. It looks like implementing a first class PARTIAL1
    in a dual-semantics systems may still be complex. So what's the
    underlying problem, or, to put it another way, what is required of the
    Forth system design to enable the simple definition of such a word ?

    --
    Krishna

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ruvim@21:1/5 to Krishna Myneni on Fri Nov 4 12:50:00 2022
    On 2022-11-03 13:03, Krishna Myneni wrote:
    On 11/2/22 14:11, Ruvim wrote:
    On 2022-10-29 16:03, Krishna Myneni wrote:
    On 10/29/22 07:29, Ruvim wrote:
    [...]
    There is no need for all of the contortions of
    EXECUTE-INTERPRETIVELY and the STATE dependence of PARTIAL1 if a
    system allows

    : NAME ... [ :NONAME ... ; ] ... ;


    Well, it looks like you admit that the dual-xt approach does not
    provide any special means to define a more advanced "partial1".


    All I am saying is that the simple definition of PARTIAL1 which has
    no reference to STATE suits our purpose at hand, e.g. for closures.
    It does so regardless of whether or not a system adheres to 3.4.5 of
    the standard. The simple definition of PARTIAL1 will not pass your
    most recent test.

    I simply point out that your test of [BAR] is no drawback for systems
    which do violate 3.4.5 and allow execution of :NONAME while the
    compilation of the current definition is suspended.

    Just a side note.
    The section "3.4.5" does not restrict a system, but only a program.

    During compilation of a definition, a system may use data space at
    it's own discretion.

    And if your system provides an advanced "partial1" — it does not
    violate "3.4.5".


    I never claimed that a system in which a "first class" PARTIAL1 may be written will violate 3.4.5.


    My commented is for these fragments:

    - "whether or not a system adheres to 3.4.5"
    - "for systems which do violate 3.4.5"

    No one system can violate 3.4.5 since this section does not restrict
    systems at all.



    My claim is that a system which permits a
    :NONAME definition nested within a definition can support an advanced PARTIAL1

    Agreed.


    -- the two are different claims.





    [...]

    You are adding an extraordinary amount of complexity to allow for
    PARTIAL1 to be used in all possible corner cases -- this is simply
    not a practical approach because such complexity will be avoided by
    programmers.

    I can't agree with that, but agree with Anton's formulation: "As a
    system implementor, you may be tempted to cut corners, but that means
    you also cut the corner cases, and users of your system will get
    unpleasant surprises"[1]


    My argument is not against writing a first class PARTIAL1 which works as expected using POSTPONE '(tick) NAME>COMPILE etc.

    My issue is
    understanding what may be structurally wrong with the design of a Forth system which makes writing a first class PARTIAL1 a complex task. Dual-semantics systems go a long way towards simplifying the definition
    of first class words. It looks like implementing a first class PARTIAL1
    in a dual-semantics systems may still be complex. So what's the
    underlying problem, or, to put it another way, what is required of the
    Forth system design to enable the simple definition of such a word ?


    I don't think that implementing "partial1" via "execute-interpretively"
    is a complex task.


    Nevertheless, to implement it without "execute-interpretively", we
    should have a plumbing word set to create definitions (see also my post
    [1]).

    In my vocabulary some of these plumbing words are [2]:

    conceive ( -- ) ( C: -- colon-sys )
    \ Start compilation of a new definition.

    germ ( -- xt|0 )
    \ Return the execution token xt of the current definition,
    \ or 0 if such a definition is absent.

    birth ( -- xt ) ( C: colon-sys -- )
    \ End compilation of the current definition,
    \ return its execution token xt.

    NB: These words shall work correctly regardless whether the current
    definition is absent or present. Also, they don't enter into compilation
    state or interpretation state.

    The term "current definition" is updated:

    *current definition*: the definition whose compilation has been started
    most recently among those whose compilation hasn't been ended.


    Using these words, an implementation for an advanced "partial1" becomes
    very simple:

    : partial1 ( x xt1 -- xt2 )
    2>r conceive r> r> lit, compile, birth
    ;



    [1] Re: Naming for parsing words, 2022-05-29, 20:48Z news://t70m6s$cbt$1@dont-email.me https://groups.google.com/g/comp.lang.forth/c/6NKrBk2sh38/m/sgyW20zfAgAJ


    [2] Obtaining the xt of the current definition https://gist.github.com/ruv/e04e29c494d7dc8fc9cb1641005dc3e4


    --
    Ruvim

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)