I am a beginner in this language : GForth.
Can someone with some experience tell me what the problem is in the code below ?
Here is a definition.
: collatzcount
variable count
0 count !
{ ini } ini
begin dup 1 <> while dup . syr repeat .
count ? ;
\ redefined collatzcount ok
At this point apparently nothing is wrong. So let us try :
1 collatzcount
output
:213: Attempt to use zero-length string as a name
1 collatzcount>>><<<
Backtrace:
$7F21F04AB710 throw
$7F21F04B0008 name-too-short?
$7F21F04B1990 header
$7F21F04B1A00 Create
$7F21F04FD460 Variable
What is this mysterious "Attempt to use zero-length string as a name" ?
Just in case one wants to know, this is the definition of syr :
: syr dup 2 mod 0 = if 2 / else 3 * 1 + endif ;
But this is probably irrelevant to the question.
variable
is a defining word and works correctly only at interpreter level i.e. not within a colon definition. (This is true for all Forths, but the symptoms of violating it may vary; in particular a 'state-smart' implementation will likely give you an error during the definition, rather than waiting till you run it.)
Also count
is a preexisting (and standard) word; using it as a variable
makes the standard word inaccessible and may break things.
Finally there is no benefit in making ini
a local when the only use you make of it is to immediately re-push it.
Net:
: syr dup 2 mod 0 = if 2 / else 3 * 1 + endif ;
variable cnt
: collatzcount 0 cnt ! begin dup 1 <> while dup . syr repeat . cnt ? ;
1 collatzcount -> 1 0 ok
3 collatzcount -> 3 10 5 16 8 4 2 1 0 ok
This runs, but the count is always 0 because you never changed it. I suspect from the name you wanted to increment cnt
in the loop so at the end it prints the number of loops executed (i.e. steps) before reaching 1:
: collatzcount 0 cnt ! begin dup 1 <> while cnt @ 1+ cnt ! dup . syr repeat . cnt ? ;
3 collatzcount -> 3 10 5 16 8 4 2 1 7 ok
etc. (Break into lines and add comments to taste.)