• Re: Parsing =?UTF-8?B?dGltZXN0YW1wcz8=?=

    From mhx@21:1/5 to dxf on Sun Oct 6 08:59:23 2024
    On Sun, 6 Oct 2024 7:51:31 +0000, dxf wrote:

    Is there an easier way of doing this? End goal is a double number representing centi-secs.


    empty decimal

    : SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;
    : >INT ( adr len -- u ) 0 0 2swap >number 2drop drop ;

    : /T ( a u -- $hour $min $sec )
    2 0 do [char] : split 2swap dup if 1 /string then loop
    2 0 do dup 0= if 2rot 2rot then loop ;

    : .T 2swap 2rot cr >int . ." hr " >int . ." min " >int . ." sec " ;

    s" 1:2:3" /t .t
    s" 02:03" /t .t
    s" 03" /t .t
    s" 23:59:59" /t .t
    s" 0:00:03" /t .t

    Why don't you use the fact that >NUMBER returns the given
    string starting with the first unconverted character?
    SPLIT should be redundant.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahmed@21:1/5 to dxf on Tue Oct 8 06:08:17 2024
    On Tue, 8 Oct 2024 3:07:31 +0000, dxf wrote:

    Not bad. Here's a translation. Hopefully it's equivalent (?)

    : split ( a u c -- a2 u2 a3 u3 )
    >r 2dup r> scan 2swap 2 pick - ;

    : number ( a u -- u ) 0 0 2swap >number 2drop ;

    : xx. ( u -- ) 0 <# bl hold # # #> type ;
    : tab3. ( h m s -- ) 3 spaces ( tab) rot xx. swap xx. xx. ;

    : ts_elms ( a u -- h m s )
    2>r 0 0 0 2r> begin
    [char] : skip [char] : split dup 0> while
    number drop 5 roll drop -rot
    repeat 2drop 2drop ;

    s" 25" ts_elms tab3. 00 00 25 ok
    s" 10:25" ts_elms tab3. 00 10 25 ok
    s" 2:10:25" ts_elms tab3. 02 10 25 ok

    I know you don't care about this case, but:
    s" 1:1:" ts_elms tab3. 00 01 01 ok
    It should be 01 01 00

    Ahmed

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahmed@21:1/5 to All on Tue Oct 8 18:12:14 2024
    Hi, Here is a programme that uses your split word.
    I think it works for all combinations (formats).

    \ here begins the code

    : SPLIT ( a u c -- a2 u2 a3 u3 ) >r 2dup r> scan 2swap 2 pick - ;

    : advance 1- swap 1+ swap ;

    : .00?1
    dup 1 3 within 0= if 2drop s" 00" then
    ;

    : .00?2
    dup 0= if 2drop s" 00" exit then
    dup 1 3 within 0= if 2drop 2swap 2>r s" 00" 2swap 2r> then
    ;

    : .00?3
    dup 0= if 2drop s" 00" exit then
    dup 1 3 within 0= if 2drop 2swap 2>r s" 00" 2rot 2rot 2r> then
    ;

    : step1 [char] : split 2swap 2>r .00?1 2swap 2r> advance ;
    : step2 [char] : split 2swap 2>r .00?2 2swap 2r> advance ;
    : step3 [char] : split 2swap 2>r .00?3 2swap 2r> advance ;

    : :t s" --" 2swap step1 step2 step3 2drop 2drop ;

    : sts space type space ;
    : .hr sts ." hr" ;
    : .min sts ." min" ;
    : .sec sts ." sec" ;

    : .t 2>r 2swap .hr .min 2r> .sec ;
    \ the code finshes here.

    Some tests (gforth under wsl):

    s" 10:20:30" :t .t 10 hr 20 min 30 sec ok
    s" 1:20:30" :t .t 1 hr 20 min 30 sec ok

    s" 1:2:30" :t .t 1 hr 2 min 30 sec ok
    s" 1:2:3" :t .t 1 hr 2 min 3 sec ok
    s" :2:3" :t .t 00 hr 2 min 3 sec ok
    s" 2:3" :t .t 00 hr 2 min 3 sec ok
    s" :3" :t .t 00 hr 00 min 3 sec ok
    s" ::3" :t .t 00 hr 00 min 3 sec ok
    s" ::" :t .t 00 hr 00 min 00 sec ok
    s" :" :t .t 00 hr 00 min 00 sec ok
    s" " :t .t 00 hr 00 min 00 sec ok
    s" 1:" :t .t 00 hr 1 min 00 sec ok
    s" :1:" :t .t 00 hr 1 min 00 sec ok
    s" 10::" :t .t 10 hr 00 min 00 sec ok
    s" 10:5:" :t .t 10 hr 5 min 00 sec ok
    s" 10:5:2" :t .t 10 hr 5 min 2 sec ok

    Ahmed

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mhx@21:1/5 to dxf on Tue Jun 10 07:32:51 2025
    On Tue, 10 Jun 2025 2:31:51 +0000, dxf wrote:
    [..]
    OTOH some implementations
    are just neater and its a matter of finding them!

    [..]
    2>r 0 0 0 2r> begin
    /int 5 -roll rot drop dup while [char] : ?skip
    repeat 2drop ;
    [..]

    I don't get if you are joking or not.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to LIT on Tue Jun 10 12:48:32 2025
    In article <6ea4ccd1cb6ae8c828144444fe51fea9@www.novabbs.com>,
    LIT <zbigniew2011@gmail.com> wrote:
    Mr. Fifo - self-proclaimed "Mark Twain of Forth"
    - has no idea, that writing Forth code doesn't
    mean to move bytes around "Back and Forth"
    (where did I see that? Let's see... :D ).

    Stack jugglery means wasting CPU cycles for
    moving the bytes around - it's contrproductive.
    Variables have been invented to be used. They're
    useful, if you didn't notice, or if they didn't
    tell you that in your college, or wherever.

    Have you looked at my Roman digits?
    There are two stack words DUP used in whole, meaning that you
    use a stack item twice.
    That is in a word `_row that isn't even essential to the whole
    exercise.
    The stack shuffling is probably a sign of bad code.

    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to All on Fri Jun 20 05:36:05 2025
    Counter-example: a good number of my apps involve structs, arrays
    and signal vectors in heap memory. Stack juggling? Absolutely not.
    The code would be unreadable and a nightmare to debug.

    Factoring in smaller code portions is often impossible because
    you can't always distribute data, that inherently belongs together,
    over separate words.

    Then why factor, when with using named parameters = locals, the
    code is already short, readable, maintainable, and bug-free.

    Ask yourself why the Forth Scientific Library makes heavy use of
    locals.

    Of course things look different with simpler applications.

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mhx@21:1/5 to dxf on Fri Jun 20 07:07:43 2025
    On Fri, 20 Jun 2025 6:29:35 +0000, dxf wrote:

    On 20/06/2025 3:36 pm, minforth wrote:
    Counter-example: a good number of my apps involve structs, arrays
    and signal vectors in heap memory. Stack juggling? Absolutely not.
    The code would be unreadable and a nightmare to debug.

    Factoring in smaller code portions is often impossible because
    you can't always distribute data, that inherently belongs together,
    over separate words.

    Then why factor, when with using named parameters = locals, the
    code is already short, readable, maintainable, and bug-free.

    Ask yourself why the Forth Scientific Library makes heavy use of
    locals.

    Of course things look different with simpler applications.

    What you're saying is at the level you program, it hardly matters
    whether it's Forth or something else. It's true I have little to
    no reason to use floating-point. I did wonder why Julian Noble
    persisted with Forth.

    No, I did not say that. What I've found is that when a subject is
    really interesting to you (in my case SPICE), it pays off to restart
    from scratch in Forth (and with a Forth mind-set).

    It is not feasible (and useful) to do that with everything, but it
    does give the type of very hard-to-believe results that are reported
    for Charles Moore. Using floating-point has nothing to do with it.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mhx@21:1/5 to minforth on Fri Jun 20 06:21:40 2025
    On Fri, 20 Jun 2025 5:36:05 +0000, minforth wrote:

    Counter-example: a good number of my apps involve structs, arrays
    and signal vectors in heap memory. Stack juggling? Absolutely not.
    The code would be unreadable and a nightmare to debug.

    Factoring in smaller code portions is often impossible because
    you can't always distribute data, that inherently belongs together,
    over separate words.

    Then why factor, when with using named parameters = locals, the
    code is already short, readable, maintainable, and bug-free.

    Interesting questions. My experience says that arrays and vectors are
    ok, but structs are dangerous, (especially?) when nested. In a 'C'
    project that I contribute to, structs arbitrarily glue data together,
    and then forwardly defined macros hide the details.
    It is impossible to debug this code without tools to decompile/inspect
    the source. It is very difficult to change/rearrange/delete struct
    fields, because they may be used in other places of the code for a
    completely different purpose. The result is that structs only grow
    and nobody dares to prune them. The only remedy is to completely
    start over.

    Ask yourself why the Forth Scientific Library makes heavy use of
    locals.

    Because the original algorithms do.

    Of course things look different with simpler applications.

    And then Einstein's famous quote spoils the fun.

    -marcel

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to dxf on Fri Jun 20 08:45:38 2025
    On Fri, 20 Jun 2025 6:29:35 +0000, dxf wrote:

    On 20/06/2025 3:36 pm, minforth wrote:
    Counter-example: a good number of my apps involve structs, arrays
    and signal vectors in heap memory. Stack juggling? Absolutely not.
    The code would be unreadable and a nightmare to debug.

    Factoring in smaller code portions is often impossible because
    you can't always distribute data, that inherently belongs together,
    over separate words.

    Then why factor, when with using named parameters = locals, the
    code is already short, readable, maintainable, and bug-free.

    Ask yourself why the Forth Scientific Library makes heavy use of
    locals.

    Of course things look different with simpler applications.

    What you're saying is at the level you program, it hardly matters
    whether
    it's Forth or something else.

    But yes, it does matter! Because Forth is compact and can can run
    on devices with limited resources. With Forth I can do realtime math
    on the device without huge libraries, such as LAPACK.

    BTW from a different direction, Krishna Myneni is pursuing a similar
    path:
    http://www.euroforth.org/ef22/papers/myneni-slides.pdf

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to mhx on Fri Jun 20 11:25:15 2025
    In article <f4aaff9dbf58ca3c0e5da7fe278b5a87@www.novabbs.com>,
    mhx <mhx@iae.nl> wrote:
    On Fri, 20 Jun 2025 5:36:05 +0000, minforth wrote:

    Counter-example: a good number of my apps involve structs, arrays
    and signal vectors in heap memory. Stack juggling? Absolutely not.
    The code would be unreadable and a nightmare to debug.

    Factoring in smaller code portions is often impossible because
    you can't always distribute data, that inherently belongs together,
    over separate words.

    Then why factor, when with using named parameters = locals, the
    code is already short, readable, maintainable, and bug-free.

    Interesting questions. My experience says that arrays and vectors are
    ok, but structs are dangerous, (especially?) when nested. In a 'C'
    project that I contribute to, structs arbitrarily glue data together,
    and then forwardly defined macros hide the details.
    It is impossible to debug this code without tools to decompile/inspect
    the source. It is very difficult to change/rearrange/delete struct
    fields, because they may be used in other places of the code for a
    completely different purpose. The result is that structs only grow
    and nobody dares to prune them. The only remedy is to completely
    start over.

    I took over the maintenance of manx (that Marcel wrote) and
    I gave up on maintenance because of the structs.
    The following example uses mini objects.
    A part is a subdivision of a musical score that is played on the
    same instrument. A timeline is used to keep track of the focus
    when the playing of the piece progresses.

    Now look at Forth objects that generalizes CREATE/DOES>
    Here the actions (methods) are directly linked to the
    offset in the object ("struct"):
    Note that mbeat !mbeat (mbeat) work on the same offset (0)
    where an arbitrary value (_) is initialised (using comma `,).
    These three words can be reordered with impunity.
    The same applies to the TIED-group.
    You could interchange the TIED-group with the mbeat-group
    without affecting other parts of the program.
    Methods of the real time "field" uses !mbeat, so this group
    then must move after the beat-group.
    m/note m/beat etc. are approcimately "fields", and can be
    reordered among themselves.
    \ -----------------------------------------------
    \ The class of a time line of a part.
    \ Each part has a time line, and then there is the real time.
    class TIMELINE
    M: mbeat @ M; \ Return current play TIME.
    M: !mbeat 0 SWAP ! M; \ Initialise timeline.
    M: (mbeat) M; _ , \ The timeline of this part.

    \ The real time in TICKS is associated with the current midi time
    \ and made the reference time.
    M: reference-ticks @ M;
    M: SET-TIME ! !mbeat M;
    0 , \ Real time corresponding to mbeat = 0 .

    \ \ The moment of the latest bar, in midibeats since the start.
    \ M: latestbar M; _ ,

    M: m/note M; _ , \ The current note duration in midibeats.
    M: m/beat M; _ , \ The current beat duration in midibeats.
    M: m/measure M; 0 , \ The current measure duration in midibeats.

    \ The amount of semitones the playing is higher than the score.
    \ Negative means lower.
    M: TRANSPOSE M; 0 ,
    \ Ratio between actual and formal note duration.
    M: (ARTICULATION) M; 1 , 1 , \ Default : legato.

    M: TIED-NOTES M; HERE 20 CELLS ALLOT !BAG \ A BAG with tied ``NOTE''s.
    M: TIED! TRUE SWAP ! M; \ Next note must be tied.
    M: UNTIED! FALSE SWAP ! M; \ .. must not ..
    M: TIED? @ M; 0 , \ "This note MUST be tied."
    endclass


    Ask yourself why the Forth Scientific Library makes heavy use of
    locals.

    Because the original algorithms do.

    Case in point the original manx from Marcel did not use too
    many locals, in the new manx they are not used at all.


    Of course things look different with simpler applications.

    And then Einstein's famous quote spoils the fun.

    The new manx is eminently servicable. There are version of
    different (ARM) hardware where the lowlevel control is
    completely different (Originally meant for the parallel port
    in MSDOS). The instrument drivers are of course hardware
    dependant, they are just plugged in.
    The original instruments were percussion, where the note-off
    from midi was ignored.
    Later the organ came along, that uses the note-off midi messages,
    without any repercussions on the architecture of the program.

    Please note that I introduced many names, but not named
    "local values".


    -marcel
    --
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Hans Bezemer on Sun Jun 22 21:27:40 2025
    On Sun, 22 Jun 2025 14:35:40 +0000, Hans Bezemer wrote:
    You can repair such things by using new stack paradigms. I've added
    several ones, most of 'em inspired by others. E.g

    "swap 3OS with TOS" (SPIN, a b c -- c b a)
    "DUP 2OS" (STOW, a b -- a a b)
    <snip>
    But of course, you have to do the work. If you're incapable or too lazy
    to do the work, yeah, then you will find Forth bites you. Note that C is
    a very nice language as well. Beats Forth performance wise - so, what's
    there not to like :)

    I mostly belong to the lazy kind. Therefore, I prefer to let the
    computer
    do the tedious work before spending time on premature optimizations,
    such as stack ordering.

    So, I made me a small extension to the locals word set. Using your
    example SPIN (abc — cba), I can define it as follows:
    : SPIN { a b c == c b a } ; \ no need for additional code before ;
    or likewise for floats, doubles, strings, matrices
    : FSPIN { f: a b c == c b a } ;
    : DSPIN { d: a b c == c b a } ;
    : "SPIN { s: a b c == c b a } ;
    : MSPIN { m: a b c == c b a } ;
    Code generation and register optimization is the computer's job.

    SPIN/STOW or similar microexamples can, of course, be defined quickly
    with classic Forth stack juggling too. The power of the extension
    becomes more apparent with mixed parameter types and/or more parameters,
    and of course, with some non-trivial algorithm to solve.

    I couldn't have done this in C, but Forth allows you to modify the
    compiler until it suits your work domain.

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mhx@21:1/5 to minforth on Mon Jun 23 05:40:37 2025
    On Sun, 22 Jun 2025 21:27:40 +0000, minforth wrote:

    [..]
    So, I made me a small extension to the locals word set. Using your
    example SPIN (abc — cba), I can define it as follows:
    : SPIN { a b c == c b a } ; \ no need for additional code before ;
    or likewise for floats, doubles, strings, matrices
    : FSPIN { f: a b c == c b a } ;
    : DSPIN { d: a b c == c b a } ;
    : "SPIN { s: a b c == c b a } ;
    : MSPIN { m: a b c == c b a } ;
    Code generation and register optimization is the computer's job.

    SPIN/STOW or similar microexamples can, of course, be defined quickly
    with classic Forth stack juggling too. The power of the extension
    becomes more apparent with mixed parameter types and/or more parameters,
    and of course, with some non-trivial algorithm to solve.

    Do you mean your compiler automatically handles/allows combinations
    like
    .. 22e-12 69. A{{ ( F: -- a ) ( D: -- b ) ( M: -- c ) SPIN ...

    I found that handling mixed types explodes the code that needs
    to be written for a simple compiler like, e.g., Tiny-KISS . It
    would be great if that can be automated.

    -marcel

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minforth on Mon Jun 23 05:18:34 2025
    minforth@gmx.net (minforth) writes:
    So, I made me a small extension to the locals word set. Using your
    example SPIN (abc — cba), I can define it as follows:
    : SPIN { a b c == c b a } ; \ no need for additional code before ;

    What is the advantage of using this extension over the Forth-2012:

    : spin {: a b c :} c b a ;

    ?

    or likewise for floats, doubles, strings, matrices
    : FSPIN { f: a b c == c b a } ;

    Lack of support for other types other than cells is indeed a
    shortcoming of standard locals. In Gforth you could write that as

    : fspin {: f: a f: b f: c :} c b a ;

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2023 proceedings: http://www.euroforth.org/ef23/papers/
    EuroForth 2024 proceedings: http://www.euroforth.org/ef24/papers/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to mhx on Mon Jun 23 10:02:44 2025
    On Mon, 23 Jun 2025 5:40:37 +0000, mhx wrote:

    On Sun, 22 Jun 2025 21:27:40 +0000, minforth wrote:

    [..]
    So, I made me a small extension to the locals word set. Using your
    example SPIN (abc — cba), I can define it as follows:
    : SPIN { a b c == c b a } ; \ no need for additional code before ;
    or likewise for floats, doubles, strings, matrices
    : FSPIN { f: a b c == c b a } ;
    : DSPIN { d: a b c == c b a } ;
    : "SPIN { s: a b c == c b a } ;
    : MSPIN { m: a b c == c b a } ;
    Code generation and register optimization is the computer's job.

    SPIN/STOW or similar microexamples can, of course, be defined quickly
    with classic Forth stack juggling too. The power of the extension
    becomes more apparent with mixed parameter types and/or more parameters,
    and of course, with some non-trivial algorithm to solve.

    Do you mean your compiler automatically handles/allows combinations
    like
    ... 22e-12 69. A{{ ( F: -- a ) ( D: -- b ) ( M: -- c ) SPIN ...

    I found that handling mixed types explodes the code that needs
    to be written for a simple compiler like, e.g., Tiny-KISS . It
    would be great if that can be automated.

    I don't know if I got you right, because as previously
    defined, SPIN expects three integers on the data stack.

    However, following your idea, a mixed SPIN could be defined e.g.

    : XSPIN { f: a d: b m: c == c b a } ;

    that can work with

    .. 22e-12 69. A{{ XSPIN ...

    I think gforth has allowed mixed type locals for a long time,
    so they are nothing really special.

    The only new word is == which pushes the locals following
    == on the stack before the word terminates with a ; or EXIT.

    This releaves you of the need to keep track of the data stack.
    A brief stack depth check can also catch some mistakes.

    I always found the conventional syntax wasteful, where
    everything after a -- does nothing but inform the reader.

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From mhx@21:1/5 to minforth on Mon Jun 23 13:34:08 2025
    On Mon, 23 Jun 2025 10:02:44 +0000, minforth wrote:

    On Mon, 23 Jun 2025 5:40:37 +0000, mhx wrote:

    On Sun, 22 Jun 2025 21:27:40 +0000, minforth wrote:

    [..]
    Do you mean your compiler automatically handles/allows combinations
    like
    ... 22e-12 69. A{{ ( F: -- a ) ( D: -- b ) ( M: -- c ) SPIN ...

    I found that handling mixed types explodes the code that needs
    to be written for a simple compiler like, e.g., Tiny-KISS . It
    would be great if that can be automated.
    I don't know if I got you right, because as previously
    defined, SPIN expects three integers on the data stack.

    I was indeed too hasty. If items are stacked, no type conversion
    is needed if they are only reordered. (Reordering needs
    no code anyway, as it is a only a memo to the compiler.) The
    problems only arise when an cell must be translated to a complex
    extended float, or when using floats to initialize an arbitrary
    precision matrix.

    Do you really support matrix and string type locals? The former
    I only do for arbitrary precision, the latter can be handled
    with DLOCALS| .

    -marcel

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to mhx on Mon Jun 23 15:09:41 2025
    On Mon, 23 Jun 2025 13:34:08 +0000, mhx wrote:

    On Mon, 23 Jun 2025 10:02:44 +0000, minforth wrote:

    On Mon, 23 Jun 2025 5:40:37 +0000, mhx wrote:

    On Sun, 22 Jun 2025 21:27:40 +0000, minforth wrote:

    [..]
    Do you mean your compiler automatically handles/allows combinations
    like
    ... 22e-12 69. A{{ ( F: -- a ) ( D: -- b ) ( M: -- c ) SPIN ...

    I found that handling mixed types explodes the code that needs
    to be written for a simple compiler like, e.g., Tiny-KISS . It
    would be great if that can be automated.
    I don't know if I got you right, because as previously
    defined, SPIN expects three integers on the data stack.

    I was indeed too hasty. If items are stacked, no type conversion
    is needed if they are only reordered. (Reordering needs
    no code anyway, as it is a only a memo to the compiler.) The
    problems only arise when an cell must be translated to a complex
    extended float, or when using floats to initialize an arbitrary
    precision matrix.

    This is too vague for me, but perhaps it's not important anyway.
    In any case, my compiler also supports Z: type complex locals.

    Do you really support matrix and string type locals? The former
    I only do for arbitrary precision, the latter can be handled
    with DLOCALS| .

    I use a matrix stack (a depth of 10-20 items is usually sufficient).
    By default, matrix elements are 32-bit sfloats. Matrix locals
    (and mvalues) are just small structs containing matrix information
    and a pointer to the heap memory allocated for all matrix elements.

    Dynamic strings are simply 1-dimensional character matrices.

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Anton Ertl on Mon Jun 23 21:03:19 2025
    On Mon, 23 Jun 2025 5:18:34 +0000, Anton Ertl wrote:

    minforth@gmx.net (minforth) writes:
    So, I made me a small extension to the locals word set. Using your
    example SPIN (abc — cba), I can define it as follows:
    : SPIN { a b c == c b a } ; \ no need for additional code before ;

    What is the advantage of using this extension over the Forth-2012:

    : spin {: a b c :} c b a ;

    ?

    Obviously, there is no advantage for such small definitions.

    For me, the small syntax extension is a convenience when working
    with longer definitions. A bit contrived (:= synonym for TO):

    : SOME-APP { a f: b c | temp == n: flag z: freq }
    \ inputs: integer a, floats b c
    \ uninitialized: float temp
    \ outputs: integer flag, complex freq
    <: FUNC < ... calc function ... > ;>
    \ emulated embedded function using { | xt: func }
    < ... calc something ... > := temp
    < ... calc other things ... > := freq / basic formula
    < ... calc other things ... > := flag
    < ... calc correction ... > := freq / better estimation
    ;

    While working on such things, I can focus my eyes on the formulas,
    all local values are visible in one place, and I don't have to
    worry about tracking the data stack(s) for lost/accumulated items.

    As I said, it is nothing spectacular, just helpful. And to my own
    eyes, it looks neater. ;-)

    And before dxf yowls again: it is still Forth. :o)

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Hans Bezemer on Tue Jun 24 00:42:09 2025
    On Mon, 23 Jun 2025 21:20:46 +0000, Hans Bezemer wrote:

    On 23-06-2025 23:03, minforth wrote:
    On Mon, 23 Jun 2025 5:18:34 +0000, Anton Ertl wrote:

    minforth@gmx.net (minforth) writes:
    So, I made me a small extension to the locals word set. Using your
    example SPIN (abc — cba), I can define it as follows:
    : SPIN { a b c == c b a } ; \ no need for additional code before ;

    What is the advantage of using this extension over the Forth-2012:

    : spin {: a b c :} c b a ;

    ?

    Obviously, there is no advantage for such small definitions.

    For me, the small syntax extension is a convenience when working
    with longer definitions. A bit contrived (:= synonym for TO):

    : SOME-APP { a f: b c | temp == n: flag z: freq }
    \ inputs: integer a, floats b c
    \ uninitialized: float temp
    \ outputs: integer flag, complex freq
     <: FUNC < ... calc function ... > ;>
    \ emulated embedded function using { | xt: func }
     < ... calc something ... > := temp
     < ... calc other things ... > := freq  / basic formula
     < ... calc other things ... > := flag
     < ... calc correction ... > := freq  / better estimation
    ;

    While working on such things, I can focus my eyes on the formulas,
    all local values are visible in one place, and I don't have to
    worry about tracking the data stack(s) for lost/accumulated items.

    As I said, it is nothing spectacular, just helpful. And to my own
    eyes, it looks neater.  ;-)

    And before dxf yowls again: it is still Forth. :o)

    Well.. Technically everything written in Forth is Forth. But it is not canonical Forth - because if it were canonical Forth, we would have
    covered locals in "Starting Forth" - and we didn't.

    Now, let's assume we found we were wrong. But there was a chapter in "Thinking Forth" called "The stylish stack" - not "The stylish locals".
    As a matter of fact, it states that "the stack is not an array" -
    meaning: not randomly accessible. And what are locals? Right. Randomly accessible.

    So, what is this? It's a feeble imitation of C. It's not part of the
    original design. Because if it were part of the original design, you
    would find out what it means to think differently. This is merely C
    thinking. Nothing else. Certainly not Forth thinking.


    LOL ... I admit being a very non-canonical old guy :O)

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Hans Bezemer on Tue Jun 24 11:50:30 2025
    On Tue, 24 Jun 2025 9:30:35 +0000, Hans Bezemer wrote:
    'Look, Ma - I've solved Forth's biggest problem.' ;-)

    No really, I'm not kidding. When done properly Forth actually changes
    the way you work. Fundamentally. I explained the sensation at the end of
    "Why Choose Forth". I've been able to tackle things I would never have
    been to tackle with a C mindset. ( https://youtu.be/MXKZPGzlx14 )

    Like I always wanted to do a real programming language - no matter how primitive. Now I've done at least a dozen - and that particular trick
    seems to get easier by the day.

    And IMHO a lot can be traced back to the very simple principles Forth is based upon - like a stack. Or the triad "Execute-Number-Error". Or the dictionary. But also the lessons from ThinkForth.

    You'll also find it in my C work. There are a lot more "small functions"
    than in your average C program. It works for me like an "inner API". Not
    to mention uBasic/4tH - There are plenty of "one-liners" in my
    uBasic/4tH programs.

    But that train of thought needs to be maintained - and it can only be maintained by submitting to the very philosophy Forth was built upon. I
    feel like if I would give in to locals, I'd be back to being an average
    C programmer.

    I still do C from time to time - but it's not my prime language. For
    this reason - and because I'm often just plain faster when using Forth.
    It just results in a better program.

    The only thing I can say is, "it works for me". And when I sometimes
    view the works of others - especially when resorting to a C style - I
    feel like it could work for you as well.

    Nine times out of ten one doesn't need the amount of locals which are applied. One doesn't need a 16 line word - at least not when you
    actually want to maintain the darn thing. One could tackle the problem
    much more elegant.

    It's that feeling..

    Why make everything so complicated? An electrician's toolbox looks
    different from a horse smith's toolbox. You sound like a horse smith
    who frowns at the electrician's toolbox and the electrician's
    “philosophy”.

    But to each his own - make love not war. :o)

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minforth on Tue Jun 24 16:37:05 2025
    minforth@gmx.net (minforth) writes:
    On Mon, 23 Jun 2025 5:18:34 +0000, Anton Ertl wrote:

    minforth@gmx.net (minforth) writes:
    So, I made me a small extension to the locals word set. Using your >>>example SPIN (abc — cba), I can define it as follows:
    : SPIN { a b c == c b a } ; \ no need for additional code before ;

    What is the advantage of using this extension over the Forth-2012:

    : spin {: a b c :} c b a ;

    ?

    Obviously, there is no advantage for such small definitions.

    For me, the small syntax extension is a convenience when working
    with longer definitions. A bit contrived (:= synonym for TO):

    : SOME-APP { a f: b c | temp == n: flag z: freq }
    \ inputs: integer a, floats b c
    \ uninitialized: float temp
    \ outputs: integer flag, complex freq
    <: FUNC < ... calc function ... > ;>
    \ emulated embedded function using { | xt: func }
    < ... calc something ... > := temp
    < ... calc other things ... > := freq / basic formula
    < ... calc other things ... > := flag
    < ... calc correction ... > := freq / better estimation
    ;

    That's somewhat like Tevet's idea:

    @Article{tevet89,
    author = "Adin Tevet",
    title = "Symbolic Stack Addressing",
    journal = jfar,
    year = "1989",
    volume = "5",
    number = "3",
    pages = "365--379",
    url = "http://soton.mpeforth.com/flag/jfar/vol5/no3/article2.pdf",
    annote = "A local variable mechanism that uses the data stack
    for storage. The variables are accessed by {\tt PICK}
    and {\tt POST} (its opposite), which means that the
    compiler must keep track of the stack depth. Includes
    source code for 8086 F83."
    }

    However, I find that I don't need to decouple at the start *and* the
    end. If I have a word with the stack effect ( a b c -- d e ), it's
    usually straightforward to write it as:

    : myword1 {: a b c -- d e :}
    ... compute d ... ( d )
    ... compute e ... ( d e ) ;

    And if that is not possible, you can do it as follows:

    : myword3 {: a b c -- d e :}
    ... compute e ... {: e :}
    ... compute d ... ( d ) e ;

    or just

    : myword2 {: a b c -- d e :}
    ... compute e ... ( e )
    ... compute d ... ( e d )
    swap ;

    Or if you really want to make the output explict, you could also write
    it as follows:

    : myword4 {: a b c -- d e :}
    ... compute e ... {: e :}
    ... compute d ... {: d :}
    d e ;

    And of course, there are also many cases where the data flow is simple
    enough that using the stacks is sufficient.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2023 proceedings: http://www.euroforth.org/ef23/papers/
    EuroForth 2024 proceedings: http://www.euroforth.org/ef24/papers/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to Waldek Hebisch on Thu Jun 26 17:35:23 2025
    On Thu, 26 Jun 2025 5:20:13 +0000, Waldek Hebisch wrote:
    My philosophy for developing programs is "follow the problem".
    That is we a problem to solve (task to do). We need to
    understand it, introduce some data structures and specify
    needed computation. This is mostly independent from programming
    language. When problem is not well understood we need
    to do some research. In this experiments may help a lot
    and having interactive programming language in useful
    (so this is plus of Forth compared to C). Once we have
    data structures and know what computation is needed we
    need to encode (represent) this in choosen language.
    I would say that large scale structure of the program
    will be mostly independent of programming language.
    There will be differences at small scale, as different
    languages have different idioms. "Builtin" features of
    language or "standard" libraries may do significant
    part of work. Effort of coding may vary widely,
    depending how much is supported by the language and
    surroundig ecosystem and how much must be newly
    coded. Also, debugging features of programming
    system affect speed of coding.

    Frankly, I do not see how missing language features
    can improve design. I mean, there are people who
    try to use fancy features when thay are not needed.
    But large scale structure of a program should not be
    affected by this. And at smaller scale with some
    experience it is not hard to avoid unneeded features.
    I would say that there are natural way to approach
    given problem and usually best program is one that
    follows natural way. Now, if problem naturally needs
    several interdependent attributes we need to represnt
    them in some way. If dependence is naturaly in stack
    way, than stack is a good fit. If dependence is not
    naturaly in a stack way, using stack may be possible
    after some reorganisation. But may experience is
    that if a given structure does not naturally appear
    after some research, than reorganisation is not
    very likely to lead to such structure. And even if
    one mananges to tweak program to such structure, it
    is not clear if it is a gain. Anyway, there is substantial
    number of problem where stack is unlikely to work in
    natural way. So how to represnt attributes? If they
    are needed only inside a single function, than natural
    way is using local variables. One can use globals, but
    for variables that are not needed outside a function
    this in unnatural. One can use stack juggling, this
    works, but IMO is unnatural. One can collect attributes
    in a single structure dynamically allocated at
    function entry and freed at exit. This works, but
    again is unnatural and needs extra code.

    You have some point about length of functions. While
    pretty small functions using locals are possible, I
    have a few longer functions where main reason for keeping
    code in one function is because various parts need access
    to the same local variables. But I doubt that eliminating
    locals and splitting such functions leads to better code:
    we get a cluster of function which depend via common
    attibutes.

    These are my observations as well. It all depends on the problem
    that you are facing. Now there are some guys who behave
    like self-declared Forth mullahs who shout heresy against
    those who don't DUP ROT enough.

    Is theirs the Forth philosophy?? Really?? I thought the main
    Forth principle was "keep it simple". When stack reordering
    is the easier way, do it. When using locals is the easier way,
    do it. If a few helper words make it easier, use them.

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From minforth@21:1/5 to LIT on Fri Jun 27 00:50:29 2025
    On Thu, 26 Jun 2025 18:18:56 +0000, LIT wrote:

    These are my observations as well. It all depends on the problem
    that you are facing. Now there are some guys who behave
    like self-declared Forth mullahs who shout heresy against
    those who don't DUP ROT enough.

    I realizad that (fortunately) long ago - actually
    Stephen Pelc made me realized that (thanks) - see
    the old thread "Vector additon" here:

    https://groups.google.com/g/comp.lang.forth/c/m9xy5k5BfkY/m/qoq664B9IygJ

    ...and in particular this message:

    https://groups.google.com/g/comp.lang.forth/c/m9xy5k5BfkY/m/-SIr9AqdiRsJ

    Vector addition, particularly dot products (used in matrix
    multiplication),
    can produce nasty results due to rounding error accumulation.

    My solution was to create a special Kahan summation primitive: https://en.wikipedia.org/wiki/Kahan_summation_algorithm

    --

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to minforth on Sun Jun 29 15:13:14 2025
    minforth@gmx.net (minforth) writes:
    Now there are some guys who behave
    like self-declared Forth mullahs who shout heresy against
    those who don't DUP ROT enough.

    The more common complaint is that you use some feature they dislike
    (typically locals) when you would otherwise DUP ROT instead. But they
    then like to tell us that real Forthers can refactor the code such
    that the DUP ROT becomes unnecessary. The discussion often stops
    there. But in some cases, we also read the praises of using global
    variables. Why are locals bad in their opinion and global variables
    good?

    Is theirs the Forth philosophy?? Really?? I thought the main
    Forth principle was "keep it simple". When stack reordering
    is the easier way, do it. When using locals is the easier way,
    do it.

    The question here is: What is "it" that one should keep simple.

    One answer: Keep the Forth system simple (even at the cost of making
    Forth source code harder to write).

    Your answer is different: Keep the Forth source code simple (and you
    mean "easy to write").

    I think focusing on only one of these aspects does not minimize the
    overall complexity. And if somebody argues with simplicity but
    ignores the big picture, the argument has no merit.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2023 proceedings: http://www.euroforth.org/ef23/papers/
    EuroForth 2024 proceedings: http://www.euroforth.org/ef24/papers/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Anton Ertl@21:1/5 to LIT on Sun Jun 29 20:25:19 2025
    zbigniew2011@gmail.com (LIT) writes:
    The more common complaint is that you use some feature they dislike
    (typically locals) when you would otherwise DUP ROT instead.

    But aren't 'locals' actually PICK/ROLL in disguise?

    As far as the act of programming is concerned, no. If I would think
    about using PICK and ROLL, I would write the code that way.

    As far as the resulting source code is concerned, no. The code looks
    so different from code using PICK and ROLL, that I don't see any
    relation.

    As far as the compilation of code with locals is concerned, many
    systems put locals on the return stack (at least conceptually), or
    (Gforth) on a separate locals stack. So, if anything it's
    return-stack (or locals-stack) accesses in disguise.

    As far as the resulting code is concerned what that looks like depends
    on the code generator of the Forth system. In particular, ntf/lxf is analytical about the data stack *and* the return stack, and in one
    case (3DUP) compiled code using PICK and code using locals to the same
    machine code. However, even for ntf/lxf you can write code where the conceptual use of the return stack becomes reified.

    - anton
    --
    M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
    comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
    New standard: https://forth-standard.org/
    EuroForth 2023 proceedings: http://www.euroforth.org/ef23/papers/
    EuroForth 2024 proceedings: http://www.euroforth.org/ef24/papers/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to All on Mon Jun 30 13:07:53 2025
    In article <0cd5e9d5959101c1efa68a2d6d630e23@www.novabbs.com>,
    Aren't 'locals' actually PICK/ROLL in disguise?

    This is a silly question. "disguise" is actually appearance.
    But the appearance of the code is what this is all about.
    So the important question is "are locals preferable to
    PICK/ROLL in appearance?" Clearly they are.

    [I personnally avoid using any of the two.]

    Groetjes Albert
    --
    The Chinese government is satisfied with its military superiority over USA.
    The next 5 year plan has as primary goal to advance life expectancy
    over 80 years, like Western Europe.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ahmed@21:1/5 to Paul Rubin on Mon Jun 30 10:25:46 2025
    On Mon, 30 Jun 2025 9:44:35 +0000, Paul Rubin wrote:



    : 3DUP ( a b c -- a b c a b c ) 3 PICK 3 PICK 3 PICK ;



    I think it must be 2 in lieu of 3, like this:

    : 3DUP ( a b c -- a b c a b c ) 2 PICK 2 PICK 2 PICK ;

    And I think it is for this type of errors, PICK must be used carefully.

    Ahmed

    --

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