Remix.run Logo
andrewla 3 days ago

A million times this. The syntax is not difficult to see, but the action seems mysterious.

The article gives an example

    > : buzz? 5 mod 0 = IF ." Buzz" THEN ;
Seems to work okay.

What about immediate mode?

    > 10 5 mod 0 = IF ." Buzz" THEN ;
    action is not a function
Well, I guess that does it for me.

Factor, another stack-based languages, has a more legible version of this, where you can push an anonymous lambda onto the stack. As I recall from my days of programming HP-48's, that used a similar mechanism. (Not checking my syntax here)

    > 5 mod 0 = << "buzz" print >> if
Would have a similar effect. Each entry makes sense -- the << switches from immediate mode to store mode (or some similar concept), and everything ends up on the stack. "If" is just a function that takes a boolean and a closure:

    > 10
    level: 0 ; stack: [10]
    > 5
    level: 0 : stack: [10 5]
    > mod
    level: 0 ; stack [0]
    > 0
    level: 0 ; stack [0 0]
    > =
    level: 0 ; stack [true]
    > <<
    level: 1 ; stack [true] []
    > "buzz"
    level: 1 ; stack [true] ["buzz"]
    > print
    level: 1 ; stack [true] ["buzz" print]
    > >>
    level: 0 ; stack [true pointer_to_function]
    > if
    "buzz"
    level: 0 ; stack []
But I don't understand what Forth is doing.
kragen 2 days ago | parent [-]

Forth control structures don't work in interpret state because control structures involve executing code out of order: jumping from the end of a loop back to its beginning, etc. In interpret state there's nowhere to jump to. So you have to put control structures inside a colon definition for them to work. Also true of strings in traditional Forths, but GForth just dynamically allocates some memory and leaks it instead.