forthgforth

gforth : Attempt to use zero-length string as a name


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.


Solution

  • 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.)