How do I define constants in EK9?
← Constants and Immutability · Ref: Q140
EK9 provides a dedicated 'defines constant' block at module level for declaring named constant values. Constants use the declaration operator <- with a literal value, and the type is inferred from the literal form.
DEFINES CONSTANT BLOCK
Constants are declared at module level inside a 'defines constant' block:
defines constant maxRetries <- 10 greeting <- "Hello" Pi <- 3.142
Each constant uses <- with a literal. No type annotation is needed because EK9 infers the type from the literal syntax.
ALL 18 CONSTANT-ELIGIBLE TYPES
Only built-in value types can be constants. EK9 supports exactly 18 types:
Integer 42, 0xFF, 0b1010 Float 3.14, 2.0 Bits 0b1010 (bit manipulation) Boolean true, false Character 'A', 'z' String "Hello" Time 10:30, 23:59:59 Date 2024-01-15 DateTime 2024-01-15T10:30:00Z Duration PT2H, PT30M Millisecond 500ms, 1000ms Dimension 2m, 100cm, 5.2kg Resolution 300dpi, 72dpi Colour #FF0000, #AB6F2B Money 12.50#USD, 100#GBP RegEx /[a-z]+/, /[S|s]te(?:ven?|phen)/ Version 1.0.0-1, 2.3.4-0 Path $?.some.path
User-defined classes and records cannot be constants because copy-on-access requires compiler-known copy constructors that only built-in types guarantee.
NATIVE LITERAL SYNTAX
EK9 provides domain-specific literal syntax for many types. You write Money as 12.50#USD, Colour as #FF0000, Duration as PT2H, Dimension as 2m, and Date as 2024-01-15. These are not strings that get parsed at runtime; they are native literals that the compiler understands directly.
NAMING CONVENTIONS
EK9 does not enforce a naming convention for constants. Common styles include UPPER_CASE (like MAX_RETRIES) and camelCase (like maxRetries). Choose a convention and apply it consistently across your project.
See Q23 for the full list of built-in types. See Q31 for Date and Time details. See Q35 for Money. See Q36 for Dimension. See Q141 for how constants are protected via copy-on-access. See Q143 for how EK9 constants compare to const/final/static in other languages. See Q142 for constants across modules. See Q317 for magic literal detection and why constants should be named.
Example
defines module qa.constants.definition defines constant maxRetries <- 10 Pi <- 3.142 greeting <- "Hello" isEnabled <- true initial <- 'A' noon <- 12:00 releaseDate <- 2024-01-15 launchTime <- 2024-01-15T10:30:00Z timeout <- PT30M halfSecond <- 500ms pageWidth <- 2m screenDpi <- 300dpi brandColour <- #AB6F2B maxPayment <- 300000#USD matchSteves <- /[S|s]te(?:ven?|phen)/ appVersion <- 1.0.0-1 configPath <- $?.app.config defines program DefineConstantsDemo() stdout <- Stdout() // Numeric constants stdout.println(`Max retries: ${maxRetries}`) stdout.println(`Pi: ${Pi}`) // Text and character stdout.println(`Greeting: ${greeting}`) stdout.println(`Initial: ${initial}`) stdout.println(`Enabled: ${isEnabled}`) // Temporal constants stdout.println(`Noon: ${noon}`) stdout.println(`Release: ${releaseDate}`) stdout.println(`Launch: ${launchTime}`) stdout.println(`Timeout: ${timeout}`) stdout.println(`Half second: ${halfSecond}`) // Domain constants stdout.println(`Page width: ${pageWidth}`) stdout.println(`Screen DPI: ${screenDpi}`) stdout.println(`Brand colour: ${brandColour}`) stdout.println(`Max payment: ${maxPayment}`) stdout.println(`Version: ${appVersion}`) stdout.println(`Config: ${configPath}`)
Common mistakes
E50001 — Renaming 'maxRetries' to 'maxretries' breaks all references since EK9 is case-sensitive. The constant name must match exactly wherever it is used. See ek9 -h E50001 for details.
Incorrect:
maxretries <- 10
Correct:
maxRetries <- 10
E07890 — Constants declared in a 'defines constant' block are immutable. You cannot reassign maxRetries after declaration. Read the constant or assign it to a mutable variable instead. See ek9 -h E07890 for details.
Incorrect:
maxRetries := 20
Correct:
stdout.println(`Max retries: ${maxRetries}`)
E50001 — EK9 is case-sensitive. The constant is 'maxRetries' not 'MAX_RETRIES'. EK9 uses camelCase for all identifiers including constants. See ek9 -h E50001 for details.
Incorrect:
stdout.println(`Max retries: ${MAX_RETRIES}`)
Correct:
stdout.println(`Max retries: ${maxRetries}`)
E50060 — EK9 does not have toString(). Use string interpolation or the $ operator. See ek9 -h E50060 for details.
Incorrect:
stdout.println(Pi.toString())
Correct:
stdout.println(`Pi: ${Pi}`)
Other ways to ask this
- How do I declare constants in EK9?
- What types can be constants in EK9?
- What is the defines constant block?
Coming from another language?
Java: static final fields, no dedicated constant block. Rust: const for compile-time values, limited to scalar-like types. Go: const block for basic types only (no structs/slices/maps). Kotlin: const val for primitives and String only. EK9: defines constant block supporting 18 types including Money, Colour, Dimension with native literal syntax and copy-on-access immutability.
Keywords: constant, define, immutable, inference, type, module, value, fixed, literal