Next: , Previous: Variables, Up: Defining Words


5.9.3 Constants

Constant allows you to declare a fixed value and refer to it by name. For example:

     12 Constant INCHES-PER-FOOT
     3E+08 fconstant SPEED-O-LIGHT

A Variable can be both read and written, so its run-time behaviour is to supply an address through which its current value can be manipulated. In contrast, the value of a Constant cannot be changed once it has been declared1 so it's not necessary to supply the address – it is more efficient to return the value of the constant directly. That's exactly what happens; the run-time effect of a constant is to put its value on the top of the stack (You can find one way of implementing Constant in User-defined Defining Words).

Forth also provides 2Constant and fconstant for defining double and floating-point constants, respectively.

Constant       w "name" –         core       “Constant”

Define a constant name with value w.

name execution: – w

2Constant       w1 w2 "name" –         double       “two-constant”

fconstant       r "name" –         float       “f-constant”

Constants in Forth behave differently from their equivalents in other programming languages. In other languages, a constant (such as an EQU in assembler or a #define in C) only exists at compile-time; in the executable program the constant has been translated into an absolute number and, unless you are using a symbolic debugger, it's impossible to know what abstract thing that number represents. In Forth a constant has an entry in the header space and remains there after the code that uses it has been defined. In fact, it must remain in the dictionary since it has run-time duties to perform. For example:

     12 Constant INCHES-PER-FOOT
     : FEET-TO-INCHES ( n1 -- n2 ) INCHES-PER-FOOT * ;

When FEET-TO-INCHES is executed, it will in turn execute the xt associated with the constant INCHES-PER-FOOT. If you use see to decompile the definition of FEET-TO-INCHES, you can see that it makes a call to INCHES-PER-FOOT. Some Forth compilers attempt to optimise constants by in-lining them where they are used. You can force Gforth to in-line a constant like this:

     : FEET-TO-INCHES ( n1 -- n2 ) [ INCHES-PER-FOOT ] LITERAL * ;

If you use see to decompile this version of FEET-TO-INCHES, you can see that INCHES-PER-FOOT is no longer present. To understand how this works, read Interpret/Compile states, and Literals.

In-lining constants in this way might improve execution time fractionally, and can ensure that a constant is now only referenced at compile-time. However, the definition of the constant still remains in the dictionary. Some Forth compilers provide a mechanism for controlling a second dictionary for holding transient words such that this second dictionary can be deleted later in order to recover memory space. However, there is no standard way of doing this.


Footnotes

[1] Well, often it can be – but not in a Standard, portable way. It's safer to use a Value (read on).