Constants and Constant Expressions

A constant is a symbol that is bound to the value of a constant expression. Constant expressions are restricted to depend only on the following categories of values and operations, because these are either built into the language or declared and evaluated before semantic analysis of the constant expression:

  • literals
  • built-in operators
  • previously declared constants and compile-time variables
  • previously declared macros and templates
  • previously declared procedures that have no side effects beyond possibly modifying compile-time variables

A constant expression can contain code blocks that may internally use all Nim features supported at compile time (as detailed in the next section below). Within such a code block, it is possible to declare variables and then later read and update them, or declare variables and pass them to procedures that modify them. However, the code in such a block must still adhere to the restrictions listed above for referencing values and operations outside the block.

The ability to access and modify compile-time variables adds flexibility to constant expressions that may be surprising to those coming from other statically typed languages. For example, the following code echoes the beginning of the Fibonacci series at compile time. (This is a demonstration of flexibility in defining constants, not a recommended style for solving this problem!)

  1. import strformat
  2. var fib_n {.compileTime.}: int
  3. var fib_prev {.compileTime.}: int
  4. var fib_prev_prev {.compileTime.}: int
  5. proc next_fib(): int =
  6. result = if fib_n < 2:
  7. fib_n
  8. else:
  9. fib_prev_prev + fib_prev
  10. inc(fib_n)
  11. fib_prev_prev = fib_prev
  12. fib_prev = result
  13. const f0 = next_fib()
  14. const f1 = next_fib()
  15. const display_fib = block:
  16. const f2 = next_fib()
  17. var result = fmt"Fibonacci sequence: {f0}, {f1}, {f2}"
  18. for i in 3..12:
  19. add(result, fmt", {next_fib()}")
  20. result
  21. static:
  22. echo display_fib