Colon definitions are very flexible, so you can write a defining word that defines a new colon definition at its run-time. Here is an example:
: myconstant {: w -- :} : w postpone literal postpone ; ;
When defining 5 myconstant five
, myconstant
first
stashes w in a local (for reasons explained later), then calls
:
, which starts the definition of five
. Then it uses
postpone literal
(see Compiling words) to compile w
(i.e., 5) into this colon definition, and then postpone ;
to
end it. You can look at the result with see five
:
: five #5 ;
Can’t we just leave w on the data stack for consumption by
postpone literal
? No: :
pushes a colon-sys on the data
stack, so we have to first move w elsewhere so we can later access
it. In this example, we used a local variable, but moving w on
the return stack and back would also have been an option.
A more convenient, but Gforth-specific way to write myconstant
is:
: myconstant {: w -- :} : ]] w ; [[ ;
The features used in this code are explained elsewhere (see Macros).
A disadvantage of this approach is that it consumes more memory than
the approach of the next section: E.g, here are the memory costs of
defining five
with the various implementations:
builtin : does> set-does> opt 48 64 48 48 48 bytes header+threaded code 0 23 0 0 0 bytes native code 16 16 32 16 16 compiled threaded code 4 23 34 7 4 compiled native code
Builtin refers to using constant
, : to using
myconstant
(defined above), does> to using
myconstant2
, set-does> to using myconstant3
(both
from see User-defined defining words using create), and opt to
using myconstant4
(see User-defined compile,
).
The lines where the label starts with “bytes” report the space
consumption of defining the word five
itself; the native code
is for gforth-fast on AMD64 (native code for the gforth engine is
larger).
The lines where the label starts with “compiled” report the space
consumption (also in bytes) for the invocation of five
in the
word : foo five * ;
. The native code can be bigger or smaller
in other contexts.