• value-flavoured structures (was: Avoid treating the stack as anarray)

    From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Fri Sep 27 12:15:48 2024
    From Newsgroup: comp.lang.forth

    On 2024-09-15 20:16, Anton Ertl wrote:
    Stephen Pelc <stephen@vfxforth.com> writes:
    [...]
    However, higher level source code has been much
    in demand. An example is Nick Nelson's value flavoured structures,
    which are of particular merit when converting code from 32 bit to
    64 bit host Forths.

    Gforth has worked on 64-bit hosts since early 1996, and I found that
    Forth code tends to have fewer portability problems between 32-bit and
    64-bit platforms than C code, and that's not just my code, the
    applications in appbench and many others are also quite portable.

    A major merit for value-flavoured structures is that you can change
    the field size (e.g, from 1 byte to 2 bytes or vice versa) without
    changing all the code accessing those fields. That's independent of
    cell size.

    Yes, you can change the field size, but only as far as its value
    occupies the same number of a stack items and the stack is the same.

    For example, it's impossible to change n to d, n to r, or vice versa,
    without changing all the code accessing those fields.

    Similar for the word `to` — `to` applies to the words created with
    `value`, `fvalue`, `2value`. But the source code around `to foo` (and
    `foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
    changed without changing the source code around where it is used.


    Higher level (more polymorphic) source code in Forth is possible when
    all values are boxed [1]


    [1] <https://en.wikipedia.org/wiki/Boxing_(computer_science)>


    --
    Ruvim

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From minforth@minforth@gmx.net (minforth) to comp.lang.forth on Fri Sep 27 08:51:05 2024
    From Newsgroup: comp.lang.forth

    On Fri, 27 Sep 2024 8:15:48 +0000, Ruvim wrote:
    For example, it's impossible to change n to d, n to r, or vice versa,
    without changing all the code accessing those fields.

    Similar for the word `to` — `to` applies to the words created with
    `value`, `fvalue`, `2value`. But the source code around `to foo` (and
    `foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
    changed without changing the source code around where it is used.

    Higher level (more polymorphic) source code in Forth is possible when
    all values are boxed [1]

    I don't know what compiler you use, but my values and locals
    are certainly not boxed. TO et al (+TO *TO := *= ++ += *+) will
    inspect their type and generate the appropriate machine code
    without me having to change the source code if I change the type.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From mhx@mhx@iae.nl (mhx) to comp.lang.forth on Fri Sep 27 09:38:09 2024
    From Newsgroup: comp.lang.forth

    On Fri, 27 Sep 2024 8:51:05 +0000, minforth wrote:

    I don't know what compiler you use, but my values and locals
    are certainly not boxed. TO et al (+TO *TO := *= ++ += *+) will
    inspect their type and generate the appropriate machine code
    without me having to change the source code if I change the type.

    You mean ...

    44e fvalue a
    1 +TO a

    .. works?

    -marcel
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Fri Sep 27 16:27:18 2024
    From Newsgroup: comp.lang.forth

    On 2024-09-27 12:51, minforth wrote:
    On Fri, 27 Sep 2024 8:15:48 +0000, Ruvim wrote:
    For example, it's impossible to change n to d, n to r, or vice versa,
    without changing all the code accessing those fields.

    Similar for the word `to` — `to` applies to the words created with
    `value`, `fvalue`, `2value`. But the source code around `to foo` (and
    `foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
    changed without changing the source code around where it is used.

    Higher level (more polymorphic) source code in Forth is possible when
    all values are boxed [1]

    I don't know what compiler you use, but my values and locals
    are certainly not boxed. TO et al (+TO *TO := *= ++ += *+) will
    inspect their type and generate the appropriate machine code
    without me having to change the source code if I change the type.

    I said about the source code *around* the usage places.

    For example:

    0 value foo
    \ ...
    foo 1+ to foo

    If we change the kind of `foo` to "floating-point" as:

    0e fvalue foo

    or to "double-cell" as:

    0. 2value foo

    then we should also updated all the places where 'to foo' or 'foo' is used:

    foo 1e + to foo

    or

    foo 1. d+ to foo



    In this sense, the code is not polymorphic.



    --
    Ruvim

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From minforth@minforth@gmx.net (minforth) to comp.lang.forth on Fri Sep 27 12:46:32 2024
    From Newsgroup: comp.lang.forth

    On Fri, 27 Sep 2024 12:27:18 +0000, Ruvim wrote:
    I said about the source code *around* the usage places.

    I see. Forth has only type-specific - or should one rather
    say - stack-specific operators.

    Introduce variant data-types, as some BASIC compilers have,
    you really have to invent a new 'Forthish' dialect. Probably
    useless for embedded applications.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Fri Sep 27 23:28:18 2024
    From Newsgroup: comp.lang.forth

    On 2024-09-27 16:46, minforth wrote:
    On Fri, 27 Sep 2024 12:27:18 +0000, Ruvim wrote:
    I said about the source code *around* the usage places.

    I see. Forth has only type-specific - or should one rather
    say - stack-specific operators.

    Introduce variant data-types, as some BASIC compilers have,
    you really have to invent a new 'Forthish' dialect.

    Such dialects, or better said, descendants, already exist.

    For example: Factor, StrongForth.


    Probably useless for embedded applications.

    Agreed.


    --
    Ruvim

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Fri Sep 27 19:13:36 2024
    From Newsgroup: comp.lang.forth

    Ruvim <ruvim.pinka@gmail.com> writes:
    Such dialects, or better said, descendants, already exist.
    For example: Factor, StrongForth.
    Probably useless for embedded applications.
    Agreed.

    Factor is sort of a Lisp dialect that is garbage collected, I think. So maybe not great for embedded. StrongForth, I thought, was like regular Forth but with a type system. That shouldn't be a problem unless there are other
    issues. Ada is strongly typed, and C++ is sort-of-strongly typed, and both
    are used in embedded apps all the time.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sat Sep 28 14:04:50 2024
    From Newsgroup: comp.lang.forth

    On 28/09/2024 5:28 am, Ruvim wrote:
    On 2024-09-27 16:46, minforth wrote:
    ...
    Probably useless for embedded applications.

    Agreed.

    Which means what?


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From dxf@dxforth@gmail.com to comp.lang.forth on Sat Sep 28 14:19:22 2024
    From Newsgroup: comp.lang.forth

    On 28/09/2024 12:13 pm, Paul Rubin wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    Such dialects, or better said, descendants, already exist.
    For example: Factor, StrongForth.
    Probably useless for embedded applications.
    Agreed.

    Factor is sort of a Lisp dialect that is garbage collected, I think. So maybe
    not great for embedded. StrongForth, I thought, was like regular Forth but with a type system. That shouldn't be a problem unless there are other issues. Ada is strongly typed, and C++ is sort-of-strongly typed, and both are used in embedded apps all the time.

    Is it not the endless comparison between forth and other languages
    that invites all these 'innovations'? If there were no comparison,
    there'd be no standards, no conformity, nor those things that make
    one language and their programmers indistinguishable from another.
    There might be creativity instead of imitation.

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Fri Sep 27 22:38:23 2024
    From Newsgroup: comp.lang.forth

    dxf <dxforth@gmail.com> writes:
    Is it not the endless comparison between forth and other languages
    that invites all these 'innovations'?

    I don't understand this question. Forth is a language designed for a
    certain milieu and that embraced a certain philosophy. That's
    legitimate. Other languages were designed in different settings or
    pursued different goals. Also legit.

    Re your other question about Factor and embedded programming, the
    traditional thought is that GC'd languages are subject to unpredictable
    pauses while the GC runs, and it can be hard to guarantee bounds on
    their memory footprint. Neither of those are friendly to realtime requirements.

    While these issues can sometimes be bypassed with fancy algorithms,
    traditional embedded approaches tend to reject GC, and avoid too much
    use of dynamic memory allocation in general.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Sat Sep 28 13:21:50 2024
    From Newsgroup: comp.lang.forth

    In article <87zfnscypb.fsf@nightsong.com>,
    Paul Rubin <no.email@nospam.invalid> wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    Such dialects, or better said, descendants, already exist.
    For example: Factor, StrongForth.
    Probably useless for embedded applications.
    Agreed.

    Factor is sort of a Lisp dialect that is garbage collected, I think. So maybe

    I'd say factor is a Forth with lispy features, like garbage collecting.

    not great for embedded. StrongForth, I thought, was like regular Forth but >with a type system. That shouldn't be a problem unless there are other >issues. Ada is strongly typed, and C++ is sort-of-strongly typed, and both >are used in embedded apps all the time.

    A strong type system is not a problem for embedded applications, as long
    as there is a means to defeat the type system.
    Ada was designed with this in mind, making distinction between safe and
    unsafe modules. Remember that c++ was an afterthought after c that was
    not well designed in the first place.

    Strong typing can be annoying. I remember wasting time passing a filename
    to function that expected a `const char *` or something, and it is
    by no means obvious what you have to do, so you are lured into casting.
    A lot of people do not understand that casting is a means to defeat the
    type system, so that you loose the advantages.

    Groetjes Albert
    --
    Temu exploits Christians: (Disclaimer, only 10 apostles)
    Last Supper Acrylic Suncatcher - 15Cm Round Stained Glass- Style Wall
    Art For Home, Office And Garden Decor - Perfect For Windows, Bars,
    And Gifts For Friends Family And Colleagues.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Sat Sep 28 10:52:13 2024
    From Newsgroup: comp.lang.forth

    albert@spenarnc.xs4all.nl writes:
    A strong type system is not a problem for embedded applications, as long
    as there is a means to defeat the type system.
    Ada was designed with this in mind, making distinction between safe and unsafe modules. Remember that c++ was an afterthought after c that was
    not well designed in the first place.

    Rust has unsafe modules but I don't remember Ada having them. Ada does
    have an Unchecked_Conversion function but I don't know where this is
    really needed or how well specified it is in the language standard.

    Usually in Ada, for low level operations involving things like machine registers, you'd call subroutines written in assembly language or
    similar. Even in C you sometimes have to do that: any operating system
    written in C will contain some asm code.

    Strong typing can be annoying. I remember wasting time passing a filename
    to function that expected a `const char *` or something, and it is

    By filename do you mean a char*, or a counted string (std::string), or something? There shouldn't be a problem passing a char* to a function expecting const char*, since the function simply promises to not modify
    the string. The error is the other direction, passing a const char*
    to something that takes a char*, i.e. that doesn't make such a promise.
    For std::string there is a builtin that converts to a char* (null
    terminated string).

    by no means obvious what you have to do, so you are lured into casting.
    A lot of people do not understand that casting is a means to defeat the
    type system, so that you loose the advantages.

    Yes exactly, casting in C++ is a code smell. I'm not a C++ expert and
    haven't written a ton of C++ code, but in what I've written, I don't
    remember having needed to cast.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Paul Rubin@no.email@nospam.invalid to comp.lang.forth on Sat Sep 28 11:06:52 2024
    From Newsgroup: comp.lang.forth

    Paul Rubin <no.email@nospam.invalid> writes:
    Rust has unsafe modules but I don't remember Ada having them. Ada does
    have an Unchecked_Conversion function but I don't know where this is
    really needed or how well specified it is in the language standard.

    Added: Ada also has "overlays" so you can make two objects share the
    same machine address, ouch!

    https://en.wikibooks.org/wiki/Ada_Programming/Type_System#Overlays

    It would surprise me if SPARK allows this feature, and it also might not
    allow Unchecked_Conversion. SPARK is an Ada subset that is supposed to
    be extremely safe, and it allows a lot of static verification. I've
    been wanting to try it. It is designed for use in critical embedded
    systems.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Thu Oct 3 15:58:58 2024
    From Newsgroup: comp.lang.forth

    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-09-15 20:16, Anton Ertl wrote:
    A major merit for value-flavoured structures is that you can change
    the field size (e.g, from 1 byte to 2 bytes or vice versa) without
    changing all the code accessing those fields. That's independent of
    cell size.

    Yes, you can change the field size, but only as far as its value
    occupies the same number of a stack items and the stack is the same.

    Yes. But you can switch between different sizes that all fit into a
    cell, or between different memory sizes of floats without changing the
    rest of the code.

    Similar for the word `to` - `to` applies to the words created with
    `value`, `fvalue`, `2value`. But the source code around `to foo` (and
    `foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
    changed without changing the source code around where it is used.

    That's just as for reading the value-flavoured field; if a field
    pushes one cell, TO to the field also consumes one cell; likewise for
    float fields.

    - 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 2024: https://euro.theforth.net
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Thu Oct 3 16:32:43 2024
    From Newsgroup: comp.lang.forth

    minforth@gmx.net (minforth) writes:
    Introduce variant data-types, as some BASIC compilers have,
    you really have to invent a new 'Forthish' dialect. Probably
    useless for embedded applications.

    Joerg Voelker works on embedded projects and found value-flavoured
    fields useful already in 2017 <https://wiki.forth-ev.de/doku.php/events:tagung-2017:forth-in-grossen-projekten>.
    Nick Nelson works on (bigger) embedded projects and also finds
    value-flavoured fields useful. See <http://www.euroforth.org/ef22/papers/nelson-values.pdf> <http://www.euroforth.org/ef22/papers/nelson-values-slides.pdf> <https://www.youtube.com/watch?v=UHcLqxG7UI4>

    - 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 2024: https://euro.theforth.net
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From dxf@dxforth@gmail.com to comp.lang.forth on Fri Oct 4 13:00:35 2024
    From Newsgroup: comp.lang.forth

    On 4/10/2024 2:32 am, Anton Ertl wrote:
    minforth@gmx.net (minforth) writes:
    Introduce variant data-types, as some BASIC compilers have,
    you really have to invent a new 'Forthish' dialect. Probably
    useless for embedded applications.

    Joerg Voelker works on embedded projects and found value-flavoured
    fields useful already in 2017 <https://wiki.forth-ev.de/doku.php/events:tagung-2017:forth-in-grossen-projekten>.
    Nick Nelson works on (bigger) embedded projects and also finds value-flavoured fields useful. See <http://www.euroforth.org/ef22/papers/nelson-values.pdf> <http://www.euroforth.org/ef22/papers/nelson-values-slides.pdf> <https://www.youtube.com/watch?v=UHcLqxG7UI4>

    I wonder whether classic structures fit the forth paradigm? Whether by
    chance or lack of schooling they seem to have passed me by.

    According to Moore:

    "Forth is definitions. If you have a lot of small definitions you are
    writing Forth."

    Structures claim to avoid 'magic numbers'. But are numbers 'magic' when
    the name of the definition containing them identifies what they are?

    Example:

    \ copy memory data (ofs) to target (a)
    : SET.S ( a ofs -- ) dbuf + count rot >target place ;
    : SET.W ( a ofs -- ) dbuf + @ swap >target ! ;
    : SET.B ( a ofs -- ) dbuf + c@ swap >target c! ;

    hex
    : THIL ( -- ) 1C2 5B set.s ; \ hilight video
    : TNOR ( -- ) 1C8 61 set.s ; \ normal video
    : TEOL ( -- ) 1BC 69 set.s ; \ clear to end-of-line
    : TINS ( -- ) 1AE 6F set.s ; \ insert line
    : TDEL ( -- ) 1B4 75 set.s ; \ delete line
    : TCR ( -- ) 168 7B set.w ; \ # cols rows
    decimal

    \ modify data
    : SET$ ( ofs size -- )
    over .str change? if cr ." : " get$ rot !str end 2drop ;

    : SET# ( ofs -- )
    dup @byt . change? if ." : " get# swap !byt end drop ;

    : ?DEL ( -- ) cr ." DELETE LINE command: " $75 5 set$ ;
    : ?INS ( -- ) cr ." INSERT LINE command: " $6F 5 set$ ;
    : ?EOL ( -- ) cr ." ERASE TO EOL command: " $69 5 set$ ;
    : ?BOLD ( -- ) cr ." BOLD VIDEO command: " $5B 5 set$ ;
    : ?NORM ( -- ) cr ." NORMAL VIDEO command: " $61 5 set$ ;
    : ?ROWS ( -- ) cr ." Number of screen rows: " $7C set# ;
    : ?COLS ( -- ) cr ." Number of screen cols: " $7B set# ;

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Fri Oct 4 11:17:28 2024
    From Newsgroup: comp.lang.forth

    On 2024-10-03 19:58, Anton Ertl wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-09-15 20:16, Anton Ertl wrote:
    A major merit for value-flavoured structures is that you can change
    the field size (e.g, from 1 byte to 2 bytes or vice versa) without
    changing all the code accessing those fields. That's independent of
    cell size.

    Yes, you can change the field size, but only as far as its value
    occupies the same number of a stack items and the stack is the same.

    Yes. But you can switch between different sizes that all fit into a
    cell, or between different memory sizes of floats without changing the
    rest of the code.

    Similar for the word `to` - `to` applies to the words created with
    `value`, `fvalue`, `2value`. But the source code around `to foo` (and
    `foo`) depends on the kind of `foo`, so the kind of `foo` cannot be
    changed without changing the source code around where it is used.

    That's just as for reading the value-flavoured field; if a field
    pushes one cell, TO to the field also consumes one cell; likewise for
    float fields.


    BTW, this is the same when the separate getter and setter (as ordinary
    words) are used. Both for value-flavoured variables and value-flavoured structures.


    ### Comparison of using a to-based setter ("to foo") and a separate
    setter ("set-foo" for example) in source codes.

    1. From the lexical point of view, "to foo" and "set-foo" are almost the
    same. "to foo" can even be considered a separate fancy word with a
    space in its name.

    2. "set-foo" has a separate entry in a word list, but "to foo" has no
    its name token and execution token (in the general case [*]).
    Some people consider the lack of a separate word as an advantage (as it reduces the overall number of headers), but this says about resources
    rather than using in source codes.

    3. "set-foo" can be easily redefined (for example, if you want to check
    the assigned value to prevent some bugs in advance).
    "to foo" *cannot* be redefined. Although, one can redefine "to" to check
    its argument and have a special action when its argument is "foo" — this
    is very cumbersome.

    4. "set-foo" can be accessed using qualified names, such as
    mymodule::set-foo or mymodule( set-foo )
    A variant like "to mymodule::foo" could work,
    a variant like "to mymodule( set-foo )" cannot work.


    Bottom line: I don't see any advantages in *using* a to-based setter
    over a separate setter.



    --
    Ruvim

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Fri Oct 4 11:52:21 2024
    From Newsgroup: comp.lang.forth

    Ruvim <ruvim.pinka@gmail.com> writes:
    1. From the lexical point of view, "to foo" and "set-foo" are almost the >same. "to foo" can even be considered a separate fancy word with a
    space in its name.

    Even closer: With the to-recognizer you can write ->FOO.

    3. "set-foo" can be easily redefined (for example, if you want to check
    the assigned value to prevent some bugs in advance).
    "to foo" *cannot* be redefined. Although, one can redefine "to" to check
    its argument and have a special action when its argument is "foo" — this >is very cumbersome.

    Wrong. It can be defined: Gforth has SET-TO <https://gforth.org/manual/Words-with-user_002ddefined-TO-etc_002e.html>
    which allows you to define what TO FOO does.

    If you mean that a standard program cannot define it, true, but that's
    just a matter of what is currently standardized.

    4. "set-foo" can be accessed using qualified names, such as
    mymodule::set-foo or mymodule( set-foo )
    A variant like "to mymodule::foo" could work,
    a variant like "to mymodule( set-foo )" cannot work.

    Let's see:

    [~/gforth:152808] gforth
    Gforth 0.7.9_20241003
    Authors: Anton Ertl, Bernd Paysan, Jens Wilke et al., for more type `authors' Copyright © 2024 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html> Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
    Type `help' for basic help
    vocabulary voc ok
    also voc definitions ok
    5 value val ok
    previous ok
    voc:val ok 1
    . 5 ok
    7 to voc:val \ <---------- ok
    also voc ok
    val . 7 ok
    previous ok
    8 ->voc:val \ <----------- ok
    voc:val . 8 ok
    3 +>voc:val \ <----------- ok
    voc:val . 11 ok


    I pointed out exactly where TO VOC:VAL, ->VOC:VAL and +>VOC:VAL occur.
    No not only can it work, it already works in Gforth. And here the
    "standard program excuse" does not apply, because neither your
    qualification syntax nor Gforth's scope-recognizer are standardized.

    Bottom line: I don't see any advantages in *using* a to-based setter
    over a separate setter.

    However, lots of Forth programmers have defined VALUEs, and barely any
    have defined getters and setters. The discussions have been aboyt
    values vs. variables, not about values vs. getters and setters.

    - 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 2024: https://euro.theforth.net
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Fri Oct 4 19:17:02 2024
    From Newsgroup: comp.lang.forth

    On 2024-10-04 15:52, Anton Ertl wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    1. From the lexical point of view, "to foo" and "set-foo" are almost the
    same. "to foo" can even be considered a separate fancy word with a
    space in its name.

    Even closer: With the to-recognizer you can write ->FOO.

    3. "set-foo" can be easily redefined (for example, if you want to check
    the assigned value to prevent some bugs in advance).
    "to foo" *cannot* be redefined. Although, one can redefine "to" to check
    its argument and have a special action when its argument is "foo" — this >> is very cumbersome.

    Wrong.
    It can be defined: Gforth has SET-TO <https://gforth.org/manual/Words-with-user_002ddefined-TO-etc_002e.html> which allows you to define what TO FOO does.

    Yes, I know ))
    I wonder why a kind of "TO" is not used to set this field/property, and *maybe* a kind of "ACTION-OF" to get this property.


    If you mean that a standard program cannot define it, true,

    Of course, I mean a standard program (and that is by default).
    Otherwise my statement would be a denial of the obvious truth ;)


    but that's just a matter of what is currently standardized.

    Yes, this is by default.



    4. "set-foo" can be accessed using qualified names, such as
    mymodule::set-foo or mymodule( set-foo )
    A variant like "to mymodule::foo" could work,

    By "could work" I mean that this can potentially work in *any* system
    that have the corresponding capabilities (e.g., the Recognizers API).


    a variant like "to mymodule( set-foo )" cannot work.

    Typo: this should be read "to mymodule( foo )"



    Let's see:

    [~/gforth:152808] gforth
    Gforth 0.7.9_20241003
    Authors: Anton Ertl, Bernd Paysan, Jens Wilke et al., for more type `authors' Copyright © 2024 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
    Gforth comes with ABSOLUTELY NO WARRANTY; for details type `license'
    Type `help' for basic help
    vocabulary voc ok
    also voc definitions ok
    5 value val ok
    previous ok
    voc:val ok 1
    . 5 ok
    7 to voc:val \ <---------- ok
    also voc ok
    val . 7 ok
    previous ok
    8 ->voc:val \ <----------- ok
    voc:val . 8 ok
    3 +>voc:val \ <----------- ok
    voc:val . 11 ok

    Behaves as expected!


    I pointed out exactly where TO VOC:VAL, ->VOC:VAL and +>VOC:VAL occur.
    No not only can it work, it already works in Gforth. And here the
    "standard program excuse" does not apply, because neither your
    qualification syntax nor Gforth's scope-recognizer are standardized.

    Yes, that's right!




    Bottom line: I don't see any advantages in *using* a to-based setter
    over a separate setter.

    However, lots of Forth programmers have defined VALUEs, and barely any
    have defined getters and setters.

    Do you mean that this is due to some advantages in *using*?

    I think, this is because `VALUE` (and co.) is a very old technique that
    is provided out of the box by many systems. In contrast, to use
    separate getters and setters you need to create your own tool to define
    them.




    The discussions have been aboyt
    values vs. variables, not about values vs. getters and setters.

    This shows that some people don't like the to-based approach.

    I seen that some implementers provide "value" and "to" only for third
    party programs and don't use them themselves.


    --
    Ruvim
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Fri Oct 4 18:04:14 2024
    From Newsgroup: comp.lang.forth

    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-10-04 15:52, Anton Ertl wrote:
    It can be defined: Gforth has SET-TO
    ...
    I wonder why a kind of "TO" is not used to set this field/property, and >*maybe* a kind of "ACTION-OF" to get this property.

    Interesting idea. Maybe in some future version.

    However, lots of Forth programmers have defined VALUEs, and barely any
    have defined getters and setters.

    Do you mean that this is due to some advantages in *using*?

    I think, this is because `VALUE` (and co.) is a very old technique that
    is provided out of the box by many systems.

    Yes. Writing getters and setters is also provided out of the box.

    variable addr-x
    : x addr-x @ ;
    : set-x addr-x ! ;

    For some reason, people have not written getters and setters. The
    lack of flexibility of standard TO has not deterred them from using
    that.

    In contrast, to use
    separate getters and setters you need to create your own tool to define >them.

    Obviously not, see above. What tool do you have in mind?

    The discussions have been aboyt
    values vs. variables, not about values vs. getters and setters.

    This shows that some people don't like the to-based approach.

    Does it? Are they using getters and setters instead? No.

    I seen that some implementers provide "value" and "to" only for third
    party programs and don't use them themselves.

    Which ones? Typing WHERE TO right after startup in Gforth and in
    SwiftForth shows a number of uses of TO in both systems.

    - 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 2024: https://euro.theforth.net
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From albert@albert@spenarnc.xs4all.nl to comp.lang.forth on Fri Oct 4 23:27:22 2024
    From Newsgroup: comp.lang.forth

    In article <46519f18ba08e088b940ee517313db099de97788@i2pn2.org>,
    dxf <dxforth@gmail.com> wrote:
    On 4/10/2024 2:32 am, Anton Ertl wrote:
    minforth@gmx.net (minforth) writes:
    Introduce variant data-types, as some BASIC compilers have,
    you really have to invent a new 'Forthish' dialect. Probably
    useless for embedded applications.

    Joerg Voelker works on embedded projects and found value-flavoured
    fields useful already in 2017
    <https://wiki.forth-ev.de/doku.php/events:tagung-2017:forth-in-grossen-projekten>.
    Nick Nelson works on (bigger) embedded projects and also finds
    value-flavoured fields useful. See
    <http://www.euroforth.org/ef22/papers/nelson-values.pdf>
    <http://www.euroforth.org/ef22/papers/nelson-values-slides.pdf>
    <https://www.youtube.com/watch?v=UHcLqxG7UI4>

    I wonder whether classic structures fit the forth paradigm? Whether by >chance or lack of schooling they seem to have passed me by.

    According to Moore:

    "Forth is definitions. If you have a lot of small definitions you are
    writing Forth."

    Structures claim to avoid 'magic numbers'. But are numbers 'magic' when
    the name of the definition containing them identifies what they are?

    Example:

    \ copy memory data (ofs) to target (a)
    : SET.S ( a ofs -- ) dbuf + count rot >target place ;
    : SET.W ( a ofs -- ) dbuf + @ swap >target ! ;
    : SET.B ( a ofs -- ) dbuf + c@ swap >target c! ;

    hex
    : THIL ( -- ) 1C2 5B set.s ; \ hilight video
    : TNOR ( -- ) 1C8 61 set.s ; \ normal video
    : TEOL ( -- ) 1BC 69 set.s ; \ clear to end-of-line
    : TINS ( -- ) 1AE 6F set.s ; \ insert line
    : TDEL ( -- ) 1B4 75 set.s ; \ delete line
    : TCR ( -- ) 168 7B set.w ; \ # cols rows
    decimal

    \ modify data
    : SET$ ( ofs size -- )
    over .str change? if cr ." : " get$ rot !str end 2drop ;

    : SET# ( ofs -- )
    dup @byt . change? if ." : " get# swap !byt end drop ;

    : ?DEL ( -- ) cr ." DELETE LINE command: " $75 5 set$ ;
    : ?INS ( -- ) cr ." INSERT LINE command: " $6F 5 set$ ;
    : ?EOL ( -- ) cr ." ERASE TO EOL command: " $69 5 set$ ;
    : ?BOLD ( -- ) cr ." BOLD VIDEO command: " $5B 5 set$ ;
    : ?NORM ( -- ) cr ." NORMAL VIDEO command: " $61 5 set$ ;
    : ?ROWS ( -- ) cr ." Number of screen rows: " $7C set# ;
    : ?COLS ( -- ) cr ." Number of screen cols: " $7B set# ;


    I agree with this approach. The following example follows the
    same principle.

    My view of class is fields with DOER words that can do anything.
    So no getters and setters, but methods that work 0n an offset
    in the class data buffer.
    The advantages come on the fore handling the pesky
    termios structures. The methods could be replaced by bit savvy
    setters and getters but I don't even see how that is done.

    Note that tcget works on the whole data buffer, ixon works on the
    4 byte first part, but the address c.q. offset is the same.

    WANT class

    \ In behalf of this program, this is a supposedly general purpose setup
    \ for serial communication.

    WANT BAG
    WANT BAG-WHERE

    <SNIP>

    \ Set bits into ADDRESS according to MASK.
    : set-bits OVER @ OR SWAP ! ;

    \ Clear bits into ADDRESS according to MASK.
    : clear-bits INVERT OVER @ AND SWAP ! ;

    \ The infamous termios struct from c. See termios.h.
    \ Size must be 0x3c.
    class TERMIOS
    \ Method working on the whole struct
    \ Get and set this struct for file DESCRIPTOR.
    M: tcget TCGETS SWAP __NR_ioctl XOS ?ERRUR M;
    M: tcset TCSETSF SWAP __NR_ioctl XOS ?ERRUR M;

    \ All these methods working on the c_iflags field.
    M: ixon $0400 set-bits M;
    M: no-ixon $0400 clear-bits M;
    M: ixoff $1000 set-bits M;
    M: no-ixoff $1000 clear-bits M;
    M: ixany $0800 set-bits M;
    M: no-ixany $0800 clear-bits M;
    M: no-ix $1C00 clear-bits M;
    M: iraw $FFFF clear-bits M;
    M: c_iflag M; 4 ALLOT

    M: opost $1 set-bits M;
    M: oraw $FFFF clear-bits M;
    M: c_oflag M; 4 ALLOT

    \ All these methods working on the c_cflags field.
    M: parity $100 set-bits M;
    M: no-parity $100 clear-bits M;
    M: doublestop $40 set-bits M;
    M: no-doublestop $40 clear-bits M;
    M: size8 $30 set-bits M;
    M: size7 $30 clear-bits $10 set-bits M;
    M: set-speed-low DUP $F clear-bits SWAP get-code set-bits M;
    M: c_cflag M; 4 ALLOT

    \ All these methods working on the c_lflags field.
    M: icanon $02 set-bits M;
    M: no-icanon $02 clear-bits M;
    M: echo $08 set-bits M;
    M: no-echo $08 clear-bits M;
    M: echoe $10 set-bits M;
    M: no-echoe $10 clear-bits M;
    M: isig $01 set-bits M;
    M: no-isig $01 clear-bits M;
    M: lraw $FF clear-bits M;
    M: c_lflag M; 4 ALLOT

    M: c_line M; 1 ( !) ALLOT \ We are now at offset $11

    M: set-timeout no-icanon 5 + C! M; \ `VTIME' Timeout in DECISECONDS.
    M: set-min no-icanon 6 + C! M; \ `VMIN' Minimal AMOUNT to recieve.
    M: c_cc M;
    $34 $11 - ALLOT \ to make speeds at an offset of $34

    \ The offsets of the c_ispeed and c_ospeed are $34 $38
    \ Stolen from c in 32 and 64 bits on a 64 bits system.
    \ Set SPEED, for input and output the same.
    \ In 64 bits those don't fit, needs an extra "1 CELLS ALLOT".
    M: set-speed-high 2DUP ! 4 + ! M;
    \ ALIGN \ To 32 bits intended but unaligned word better!
    M: c_ispeed M; 4 ALLOT
    M: c_ospeed M; 4 ALLOT
    M: termios-size ^TERMIOS @ - M;
    M: termios-erase >R ^TERMIOS @ R> OVER - ERASE M;
    M: termios-compare >R ^TERMIOS @ R> OVER - CORA 1004 ?ERROR M;
    1 CELLS ALLOT
    endclass

    TERMIOS serial-port
    serial-port \ Make current

    <SNIP>

    Note that the sheer amount of bits that has to be handled is the reason
    to like its compactness. Compare it to the serial routines of gforth.

    Groetjes Albert
    --
    Temu exploits Christians: (Disclaimer, only 10 apostles)
    Last Supper Acrylic Suncatcher - 15Cm Round Stained Glass- Style Wall
    Art For Home, Office And Garden Decor - Perfect For Windows, Bars,
    And Gifts For Friends Family And Colleagues.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Sat Oct 5 15:06:47 2024
    From Newsgroup: comp.lang.forth

    On 2024-10-04 22:04, Anton Ertl wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-10-04 15:52, Anton Ertl wrote:
    It can be defined: Gforth has SET-TO
    ...
    I wonder why a kind of "TO" is not used to set this field/property, and
    *maybe* a kind of "ACTION-OF" to get this property.

    Interesting idea. Maybe in some future version.

    However, lots of Forth programmers have defined VALUEs, and barely any
    have defined getters and setters.

    Do you mean that this is due to some advantages in *using*?

    What advantages do you see in *using* the to-based setters?





    I think, this is because `VALUE` (and co.) is a very old technique that
    is provided out of the box by many systems.

    Yes. Writing getters and setters is also provided out of the box.

    variable addr-x
    : x addr-x @ ;
    : set-x addr-x ! ;

    For some reason, people have not written getters and setters.

    The length of the declaration matters. "0 value x" is far shorter than creating two additional colon-definitions. Thus, this method, which
    involves *manually* creating of separate colon definitions, is an
    inconvenient alternative (nevertheless, it is used sometimes).



    The lack of flexibility of standard TO has not deterred them from
    using that.

    This statement contains the logical fallacy "Survivorship bias" [1].

    There are different use cases. In some use cases the discussed
    flexibility is not needed, in other — it is needed.

    And you see only examples of using to-based setters when that
    flexibility is not needed. When it is need, you don't see to-based
    setters being used — they are not used.

    So your conclusion that the lack of flexibility does not deter the use
    of to-based setters is wrong. It does deter that when this flexibility
    is needed. And when this flexibility is not needed, its lack does not
    matter at all.


    [1] <https://en.wikipedia.org/wiki/Survivorship_bias>




    In contrast, to use
    separate getters and setters you need to create your own tool to define
    them.

    Obviously not, see above.

    A tool is needed for convenience. Of course, you always can do manually
    what the tool does.

    I use such tools to create a store (with setters and getters) not only
    for single-cell and cell-pair data objects ([2], but also for dynamic character strings (since 2008).

    In classic Forth the latter would look as this:

    \ Declaration (creating)
    prop( foo ) \ a property, which has the string type

    \ Usage
    "foo bar " set-foo
    foo type \ it prints "foo bar "
    "baz " join-foo
    foo type \ it prints "foo bar baz "
    "xxx" set-foo \ store another value


    [2] Defining words to create a getter and setter for a slot at once <https://gist.github.com/ruv/438d57d0af6a38e616efb59b43795e1b#file-slot-fth>


    What tool do you have in mind?

    For example, it could be a defining word "val" that is used as "val x"
    and creates the getter "x" and the setter "set-x".

    Such a word "val" can be defined like this:

    [undefined] name> [if]
    : name> ( nt -- xt )
    name>interpret dup if exit then
    drop [: -14 throw ;]
    ;
    [then]

    : val ( "name" -- )
    create 0 , [: does> @ ;] execute
    0. <# latest-name name>string holds s" set-" holds #>
    ['] : execute-parsing
    latest-name name> >body lit,
    postpone ! postpone ;
    ;

    \ Re "latest-name" see [2]

    \ test
    t{ val x -> }t
    t{ x -> 0 }t
    t{ 3 set-x -> }t
    t{ x -> 3 }t


    \ Let's redefine the setter "set-x"
    : set-x ( u -- )
    dup 10 u> abort" too big value for x"
    set-x
    ;

    t{ 4 set-x x -> 4 }t
    t{ 11 ' set-x catch 2drop x -> 4 }t


    Could you show how to implement that in Gforth when the to-based setter
    "to x" is used?

    NB: the solution must not change the original "x", it must redefine "x".
    The difference is that the new definition *can* be in a different word
    list, in which case both definitions (old and new) can be used depending
    on the context.


    [3] Proposal about "latest-name" <https://forth-standard.org/proposals/new-words-latest-name-and-latest-name-in?hideDiff#reply-1251>




    The discussions have been aboyt
    values vs. variables, not about values vs. getters and setters.

    This shows that some people don't like the to-based approach.

    Does it? Are they using getters and setters instead? No.

    How do you know this?



    I seen that some implementers provide "value" and "to" only for third
    party programs and don't use them themselves.

    Which ones? Typing WHERE TO right after startup in Gforth and in
    SwiftForth shows a number of uses of TO in both systems.

    I saw this on Reddit, in r/Forth. That was not about any of the five
    Forth systems you usually test. I don't have a link to that discussion.




    --
    Ruvim

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From anton@anton@mips.complang.tuwien.ac.at (Anton Ertl) to comp.lang.forth on Sat Oct 5 15:52:49 2024
    From Newsgroup: comp.lang.forth

    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-10-04 22:04, Anton Ertl wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-10-04 15:52, Anton Ertl wrote:
    It can be defined: Gforth has SET-TO
    ...
    I wonder why a kind of "TO" is not used to set this field/property, and
    *maybe* a kind of "ACTION-OF" to get this property.

    Interesting idea. Maybe in some future version.

    Thinking some more about it, better not:

    SET-TO SET-OPTIMIZER etc. all work on the latest definition. The
    methods that they set work on an NT or XT passed on the stack. The
    usual behaviour of defer-flavoured words is that the context is the
    same. If you have

    defer d
    ' foo is d
    action-of d

    That's always the same global D. For a defer-flavoured field,
    likewise:

    0
    value: vf
    defer: df
    constant mystruct

    create foo mystruct allot

    1 foo to vf
    ' . foo is df

    foo vf .
    2 foo df

    So having TO TO instead of SET-TO would disobey this principle.

    For COMPILE, there is the additional problem that it is a deferred
    word, so when you do "IS COMPILE," you change the behaviour for all
    uses of "COMPILE,", not just of the latest definition. The actual
    method of each definition is called OPT-COMPILE,.

    What advantages do you see in *using* the to-based setters?

    Over using SET-... words?

    1) It's a popular and convenient mechanism.

    2) I can find out the setter from looking at the central word:

    ``vf .hm
    \ output:
    opt: $7F43EB229B98
    to: $7F43EB229BE0
    extra: $7F43EB229B60
    int: noop
    comp: default-name>comp
    string: named>string
    link: named>link ok

    Ok, $7F43EB229BE0 is not very informative, but I can still make use of
    that:

    $7F43EB229BE0 xt-locate
    struct-val.fs:88
    ...
    cell ' aligned ' @ !a-table wrap+value: value: ( u1 "name" -- u2 ) \ gforth-experimental
    ...

    The lack of flexibility of standard TO has not deterred them from
    using that.

    This statement contains the logical fallacy "Survivorship bias" [1].

    There are different use cases. In some use cases the discussed
    flexibility is not needed, in other — it is needed.

    That's a very Forthy way of looking at it. The usual argument for
    getters and setters is that that flexibility might be needed in the
    future, so you don't use a mechanism like variables or values that
    does not provide this flexibility, in order to avoid having to change
    all the places where the variable or value is used, and only have to
    change the place where the getter and setter is defined. In this
    scenario value-flavoured words must not be used unless the flexibility
    for TO is provided (i.e., they must not be used in standard Forth).

    But yes, there are probably not many people with that mindset in the
    Forth community. Forth-94 seems to have had some of that, though,
    with words like GET-CURRENT and SET-CURRENT instead of a (user)
    variable CURRENT that had existing practice at the time. I wish they
    had defined GET-BASE and SET-BASE instead of BASE.

    For example, it could be a defining word "val" that is used as "val x"
    and creates the getter "x" and the setter "set-x".

    Such a word "val" can be defined like this:

    [undefined] name> [if]
    : name> ( nt -- xt )
    name>interpret dup if exit then
    drop [: -14 throw ;]
    ;
    [then]

    : val ( "name" -- )
    create 0 , [: does> @ ;] execute
    0. <# latest-name name>string holds s" set-" holds #>
    ['] : execute-parsing
    latest-name name> >body lit,
    postpone ! postpone ;
    ;

    \ Re "latest-name" see [2]

    \ test
    t{ val x -> }t
    t{ x -> 0 }t
    t{ 3 set-x -> }t
    t{ x -> 3 }t


    \ Let's redefine the setter "set-x"
    : set-x ( u -- )
    dup 10 u> abort" too big value for x"
    set-x
    ;

    t{ 4 set-x x -> 4 }t
    t{ 11 ' set-x catch 2drop x -> 4 }t


    Could you show how to implement that in Gforth when the to-based setter
    "to x" is used?

    : to-x ( u xt -- )
    >r dup 10 u> abort" too big value for x" r> >body ! ;

    to-table: x-table to-x
    ' >body x-table to-class: x-to
    0 value x
    ' x-to set-to

    4 to x x . \ prints "4"
    11 to x

    The last line produces the following error:

    *the terminal*:13:7: error: too big value for x
    11 to >>>x<<<

    NB: the solution must not change the original "x", it must redefine "x".
    The difference is that the new definition *can* be in a different word
    list, in which case both definitions (old and new) can be used depending
    on the context.

    Let's see. To make it easier to see what is going on I use a
    different name for the redefined word.

    0 value y
    synonym z y
    ' x-to set-to

    4 to y
    z . \ prints 4
    11 to y
    z . \ prints 11
    11 to z \ aborts with "error: too big value for x"

    For a bounds-checking TO I find this requirement strange, however.

    This shows that some people don't like the to-based approach.

    Does it? Are they using getters and setters instead? No.

    How do you know this?

    I see many more postings with TO than with setters and getters.

    - 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 2024: https://euro.theforth.net
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Sun Oct 6 17:12:00 2024
    From Newsgroup: comp.lang.forth

    On 2024-10-05 19:52, Anton Ertl wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-10-04 22:04, Anton Ertl wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-10-04 15:52, Anton Ertl wrote:
    It can be defined: Gforth has SET-TO
    ...
    I wonder why a kind of "TO" is not used to set this field/property, and >>>> *maybe* a kind of "ACTION-OF" to get this property.

    Interesting idea. Maybe in some future version.

    Thinking some more about it, better not:

    SET-TO SET-OPTIMIZER etc. all work on the latest definition.

    I assumed that there are methods under the hood that work on any given definition, not the latest one. Or such methods could be defined.


    The methods that they set work on an NT or XT passed on the stack.
    The usual behaviour of defer-flavoured words is that the context is
    the same. If you have

    defer d
    ' foo is d
    action-of d

    That's always the same global D. For a defer-flavoured field,
    likewise:

    0
    value: vf
    defer: df
    constant mystruct

    create foo mystruct allot

    1 foo to vf
    ' . foo is df

    foo vf .
    2 foo df

    So having TO TO instead of SET-TO would disobey this principle.

    I see. I mean methods to access/change a property of any given word,
    namely the "TO name run-time" semantics.

    Let the *setter* for a word is an execution token that identifies "TO
    name run-time" semantics for the word.

    (I understand that in Gforth, the xt of a word is passed to the method
    that implements "to", but I consider a simpler variant)



    There are several approaches to access or assign the setter for a word.



    1. "to-based" approach, but with special words instead of "is" and "action-of".

    \ setter-to ( xt.setter "name" -- )
    \ setter-of ( "name" -- xt.setter )

    \ Usage example

    0 value foo
    1 setter-of foo execute
    foo . \ prints "1"

    [: ( u -- )
    dup 10 u> abort" too big value for x"
    [ setter-of foo compiler, ]
    ;] setter-to foo


    Disadvantages:
    - a visually *unmarked* immediate argument in the input stream,
    - inconvenient to work with nt.


    2. "to-based" approach for structures

    \ name>setter ( nt -- xt.setter )
    \ to name>setter ( xt.setter nt -- )

    \ Usage example

    0 value foo
    1 "foo" find-name name>setter execute
    foo . \ prints "1"

    [: ( u -- )
    dup 10 u> abort" too big value for x"
    [ "foo" find-name name>setter compiler, ]
    ;] "foo" find-name to name>setter


    Disadvantages:
    - a visually *unmarked* immediate argument in the input stream,
    - the phrase `"foo" find-name to name>setter`
    does look like we are storing an nt from `find-name` into `name>setter`.
    (this is the same as for structures)

    A solution for the latter: use another name instead of "to"
    For example, "to-field"

    "foo" find-name to-field name>setter

    A solution for the former: mark the input argument. For example:

    "foo" find-name to-field( name>setter )




    3. Simple words

    \ name>setter ( nt -- xt.setter )
    \ name-setter! ( xt.setter nt -- )

    \ Usage example

    0 value foo
    1 "foo" find-name name>setter execute
    foo . \ prints "1"

    [: ( u -- )
    dup 10 u> abort" too big value for x"
    [ "foo" find-name name>setter compiler, ]
    ;] "foo" find-name name-setter!


    Disadvantages are unknown.






    For COMPILE, there is the additional problem that it is a deferred
    word, so when you do "IS COMPILE," you change the behaviour for all
    uses of "COMPILE,", not just of the latest definition. The actual
    method of each definition is called OPT-COMPILE,.



    In the to-based approach, "compile," should behave like a field in a structure.

    Taking into account that an optimizer (or a special compiler) should be associated with an xt (not with an nt), this could look as:

    [: ( xt -- ) >body lit, ['] @ compile, ;]
    ' foo is compiler,

    Or, with less disadvantages:

    [: ( xt -- ) >body lit, ['] @ compile, ;]
    ' foo to-field( xt-compiler )

    \ where
    : compile, ( xt -- ) dup xt-compiler execute ;




    All of the above are just ideas.


    --
    Ruvim
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Sun Oct 6 20:04:34 2024
    From Newsgroup: comp.lang.forth

    On 2024-10-05 19:52, Anton Ertl wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:

    What advantages do you see in *using* the to-based setters?

    Over using SET-... words?

    I've compared the use of a to-based setter ("to foo") versus a separate
    setter ("set-foo") in programs. (NB: not creating them, but only using)
    I do not see any advantage of "to foo" over "set-foo" at the *source
    code* level.

    And I asked about advantages in this context. Do you see any advantages
    in using (i.e., not declaration/creation) at the source code level?




    1) It's a popular and convenient mechanism.

    Agreed. But this says about knowledge and tools, not about using already defined setters in the source code.



    2) I can find out the setter from looking at the central word:

    A separate setter for a word "foo" can be checked using only standard
    words as follows:

    "set-foo" find-name .


    ``vf .hm
    \ output:
    opt: $7F43EB229B98
    to: $7F43EB229BE0
    extra: $7F43EB229B60
    int: noop
    comp: default-name>comp
    string: named>string
    link: named>link ok

    Ok, $7F43EB229BE0 is not very informative, but I can still make use of
    that:

    $7F43EB229BE0 xt-locate
    struct-val.fs:88
    ...
    cell ' aligned ' @ !a-table wrap+value: value: ( u1 "name" -- u2 ) \ gforth-experimental
    ...


    [...]

    For example, it could be a defining word "val" that is used as "val x"
    and creates the getter "x" and the setter "set-x".
    [...]
    \ Let's redefine the setter "set-x"
    : set-x ( u -- )
    dup 10 u> abort" too big value for x"
    set-x
    ;

    t{ 4 set-x x -> 4 }t
    t{ 11 ' set-x catch 2drop x -> 4 }t


    Could you show how to implement that in Gforth when the to-based setter
    "to x" is used?

    : to-x ( u xt -- )
    >r dup 10 u> abort" too big value for x" r> >body ! ;

    to-table: x-table to-x
    ' >body x-table to-class: x-to
    0 value x
    ' x-to set-to

    4 to x x . \ prints "4"
    11 to x

    The last line produces the following error:

    *the terminal*:13:7: error: too big value for x
    11 to >>>x<<<


    Thank you! As I see it, this interface is quite cumbersome for the
    specified problem, because it forces us to use two intermediate data
    objects: "to-table" and "to-class".



    NB: the solution must not change the original "x", it must redefine "x".
    The difference is that the new definition *can* be in a different word
    list, in which case both definitions (old and new) can be used depending
    on the context.

    Let's see. To make it easier to see what is going on I use a
    different name for the redefined word.

    0 value y
    synonym z y
    ' x-to set-to

    4 to y
    z . \ prints 4
    11 to y
    z . \ prints 11
    11 to z \ aborts with "error: too big value for x"

    For a bounds-checking TO I find this requirement strange, however.

    Yes, for a bounds-checking TO you probably will define checking at once,
    or redefine the word at once in the same word list.

    But in some other cases I need to have access to both old and new words,
    so I wanted to see what a Gforth-specific solution for a to-based setter
    looks like.



    --
    Ruvim
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Ruvim@ruvim.pinka@gmail.com to comp.lang.forth on Sun Oct 6 20:58:50 2024
    From Newsgroup: comp.lang.forth

    On 2024-10-05 19:52, Anton Ertl wrote:
    Ruvim <ruvim.pinka@gmail.com> writes:
    On 2024-10-04 22:04, Anton Ertl wrote:
    [...]
    The lack of flexibility of standard TO has not deterred them from
    using that.

    This statement contains the logical fallacy "Survivorship bias" [1].

    There are different use cases. In some use cases the discussed
    flexibility is not needed, in other — it is needed.

    That's a very Forthy way of looking at it. The usual argument for
    getters and setters is that that flexibility might be needed in the
    future, so you don't use a mechanism like variables or values that
    does not provide this flexibility, in order to avoid having to change
    all the places where the variable or value is used, and only have to
    change the place where the getter and setter is defined.

    Yes. This becomes even more important for libraries and standard words, because you cannot change code in programs that use the library.


    In this
    scenario value-flavoured words must not be used unless the flexibility
    for TO is provided (i.e., they must not be used in standard Forth).

    But yes, there are probably not many people with that mindset in the
    Forth community.

    I wonder how many there are :))


    Forth-94 seems to have had some of that, though,
    with words like GET-CURRENT and SET-CURRENT instead of a (user)
    variable CURRENT that had existing practice at the time. I wish they
    had defined GET-BASE and SET-BASE instead of BASE.

    Me too. Same for "STATE".

    Probably too many programs were already using the "BASE" and "STATE"
    variables in 1993. However, it was possible to discourage their use and provide a better interface for new programs.


    --
    Ruvim

    --- Synchronet 3.20a-Linux NewsLink 1.114