6.11.10.2 User-defined defining words using create

If you want the words defined with your defining words to behave differently from words defined with standard defining words, you can write your defining word like this:

: def-word ( "name" -- )
    CREATE code1
DOES> ( ... -- ... )
    code2 ;

def-word name

This fragment defines a defining word def-word and then executes it. When def-word executes, it CREATEs a new word name, and executes the code code1. The code code2 is not executed at this time. The word name is sometimes called a child of def-word.

When you execute name, the address of the body of name is pushed on the data stack and code2 is executed. The address of the body of name is the address HERE returns immediately after the CREATE, i.e., the address a created word returns by default).

You can understand the behaviour of def-word and name by considering the following definitions:

: def-word1 ( "name" -- )
    CREATE code1 ;

: action1 ( ... -- ... )
    code2 ;

def-word1 name1

Using name1 action1 is equivalent to using name.

You can use def-word to define a set of child words that behave similarly; they all have a common run-time behaviour determined by code2. Typically, the code1 sequence builds a data area in the body of the child word. The structure of the data is common to all children of def-word, but the data values are specific – and private – to each child word.

As an example, here’s how you can define myconstant2 with does>:

: myconstant2 ( w "name" -- )
    create ,
does> ( -- w )
    @ ;

Here create defines a word name, then , stores w in name’s data area, then the does> changes name’s behaviour and returns to the caller of myconstant2: When name is invoked, the new behaviour first pushes the address of the data area (as before), but then also performs the code after the does>. In the present case, this code fetches the value of the constant from the data area.

The stack effect besides the does reflects the stack effect of name execution, not the stack effect of the code after the does> (this is not common practice yet but we still recommend it).

Does> splits the definition into two subdefinitions and has a number of disadvantages. Alternatively, Gforth allows you to provide the second part as an execution token by using set-does>. So the general scheme is:

: def-word ( "name" -- ; name execution: ... -- ... )
    create code1
    xt-code2 set-does>
    code3 ;

The difference from the definition using does> is that on name execution, after pushing the data address, xt-code2 is executed, rather than calling the code after the does>. This also allows putting code3 in def-word; this is particularly relevant when you want to also use set-optimizer (see User-defined compile,) on the defined word, because does>/set-does> calls set-optimizer itself, so using set-optimizer before does>/set-does> has no effect.

Here xt-code2 could be the xt of an existing word, or it could be provided through a quotation (see Quotations).

Another advantage of set-does> is that the result is a little more efficient if the execution token passed to it is that of a primitive. This advantages comes to fruition in:

: myconstant3 ( w "name" -- ; name execution: -- w )
    create ,
    ['] @ set-does> ;

During name execution, after pushing the body address of name, @ is executed.

The efficiency advantage shows up in the comparisons of compiled code size (see User-defined defining words with colon definitions); the execution time also benefits.