Re: Factor

Factor: the language, the theory, and the practice.

Constants

Tuesday, October 29, 2024

#syntax

Factor has programmable syntax, a feature that allows for concise source code, reducing repetition and allowing the programmer to express forms and intent with minimal tokens. As an example of this, today I want to discuss constants.

You can define a word with a constant value, using syntax like this:

CONSTANT: three 3

Someone on our Factor Discord server asked if it was possible to define multiple constants in one syntax expression, to avoid the line noise of defining them one-by-one.

So, instead of these four definitions:

CONSTANT: foo 1
CONSTANT: bar $[ 2 sqrt ]
CONSTANT: baz $ bar
CONSTANT: qux \ foo

We could instead make this syntax:

SYNTAX: CONSTANTS:
    ";" [
        create-word-in
        [ reset-generic ]
        [ scan-object define-constant ] bi
    ] each-token ;

Breaking that down into steps:

  1. SYNTAX: indicates we’re defining new syntax
  2. CONSTANTS: is the name of our new syntax word
  3. ";" defines the terminator that will end our constant definitions
  4. each-token will process each token until it hits the terminator

For each constant definition, it performs these steps:

  • create-word-in creates a new word in the current vocabulary
  • reset-generic clears any generic word properties
  • scan-object reads and parses the next value
  • define-constant makes it a constant with the parsed value

And now this expression works, reducing the visual noise in our source code:

CONSTANTS:
   foo 1
   bar $[ 2 sqrt ]
   baz $ bar
   qux \ foo
;

As an aside, the different syntaxes used above are:

  • 1 is just a token parsed as a number literal
  • $[ ... ] evaluates the code inside at parse time
  • $ gets the value of another constant
  • \ gets the word object itself rather than its value

Factor’s syntax parsing words allow a great deal of flexibility in making custom DSL-style syntax forms work nicely to reduce repetition, and generate code with less effort.

I’m not sure if this is worth adding to the standard library or not, but it’s neat!