Was I missing something?yes
use variable or value for variables, not the stack
the stack is for expression evaluation
roughly everyone has this problem at first
if you'd put it in a local variable in c or js, 85% of the time you should put it in a variable in forth. start with 100% or 110% and scale back from there
yes this means your words aren't reentrant by default
this is ok, most subroutines aren't recursive
never shuffle the stack or count the elements in it. if you find yourself doing that, put the elements you wanted to access in a variable or value
then you can access them by name. this is much easier
the possibility of shuffling the stack is an attractive nuisance, like a tar pit. an occasional dup or swap or r@ is okay, but start by not using them
literally write square as
variable x
: square x ! x @ x @ * ;
or
value x
: square to x x x * ;
if that's what it takes to stop tying your code in knots
it is ok to name a variable x, its scope only extends to the next definition of an x. it's not like in c where every x needs to either be local to a subroutine or a single global unique x used by the entire program (or at least source file)
later you can graduate to sometimes replacing one local variable with the return stack and another one or occasionally two with the operand stack, but it is better for your code to be kind of boring and verbose than an incomprehensible soup of 2dup -rot tuck
forth is maybe not better than c but there is no reason to make it worse