E11064: literal in comparison/range - give it a meaningful name
What went wrong
A literal value is used directly in a comparison, relational, or range expression. Bare literals at decision points carry no semantic signal - the reader must infer what the value means from surrounding context.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 317 (How does EK9 detect magic literals?)
- ek9 -q 638 (Why should I use named constants instead of literal value...)
- ek9 -q 320 (Why does EK9 report on readability?)
Rationale
About one change in six to duplicated code introduces a bug (CQSE, "Preventing Inconsistency Bugs", drawing on Juergens et al., ICSE 2009). The partial-update problem - changing N-1 of N occurrences - is exactly how such an inconsistency bug is made.
Anquetil et al. (2022) had 26 developers classify about 24,000 literals and only about a quarter were judged "magic" - context decides, which is why EK9 reports a bare literal only where it decides something: in a comparison, a relation or a range.
For AI code analysis, a named value is immediately understood. A bare literal requires cross-referencing against context - expensive inference that a name eliminates entirely.
How to fix it
Give this literal a meaningful name, where it is written.
With tooling, ek9_extract_constant (file, the literal as written, a name) makes it a module constant and rewrites the use in one call - but only for a literal already in the file. If a tool edit was rolled back for this error, nothing was written and the literal is not in the file: define the constant first with ek9_new_construct mode:'constant' (a name, the literal as its value), or declare a local in the same edit, and use the name in the edit you resend.
By hand, choose the right scope:
- Option 1 - a local variable, for a value specific to this function (good_local.ek9 in the [EXAMPLE] section below)
- Option 2 - a named constant, for a shared domain concept (good.ek9 below: an ADULT_AGE constant compared with an age)
Use a local variable when the value is a local algorithmic concern. Use a constant when the value represents a shared domain concept that other functions might also need, or that a maintainer would need to find and change in one place.
[STRUCTURAL CONSTRAINT INSIDE RETURN-DECLARED FUNCTIONS] When the enclosing function has a returning variable, local variables CANNOT appear between the incoming parameters ('->') and the returning variable ('<-'). The function body has a strict order: the parameters, then the returning variable, then the statements (including any local variables used below). A local threshold written between the two arrows is a PARSE ERROR, not a fix.
Inside a return-declared function you have two working options:
- Option A - declare the returning variable without a value, declare the local after it, then give the returning variable its value (good_local.ek9):
isExpensive() as pure -> price as Float <- rtn as Boolean? //A local goes after the returning variable, never between '->' and '<-' expensiveThreshold <- 50.0 rtn :=? price > expensiveThreshold
- Option B - extract the threshold to a module constant (preferred when the value is a domain concept): the returning variable is then initialised directly from a comparison with the constant, as good.ek9 does.
Option B is usually cleaner for thresholds in pure functions - no local, no later assignment, one obvious place to change the value.
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E11064: literal in comparison/range - give it a meaningful name
#!ek9 defines module error.e11064.bad defines function isAdult() -> age as Integer <- rtn as Boolean: age >= 18
Fixed: Give the literal a name
#!ek9 defines module error.e11064.good defines constant ADULT_AGE <- 18 defines function isAdult() -> age as Integer <- rtn as Boolean: age >= ADULT_AGE
Fixed: A local variable names a value specific to one function - declared after the returning variable
#!ek9 defines module error.e11064.good.local defines function isExpensive() as pure -> price as Float <- rtn as Boolean? //A local goes after the returning variable, never between '->' and '<-' expensiveThreshold <- 50.0 rtn :=? price > expensiveThreshold
Questions and answers
These Q&A entries show E11064 and its fix:
- Q317: How does EK9 detect magic literals?
- Q320: Why does EK9 report on readability?
- Q321: How do I see the code quality report?
- Q322: How do I see how many times code was called and how long it took?
- Q638: Why should I use named constants instead of literal values in comparisons?
- Q1061: Write a reusable function that filters items above a threshold so I can call it from anywhere.
- Q1063: Write a complete EK9 program that reads a list of scores, filters passing ones, and prints the results.
- Q1184: Extract magic literals in comparisons into named constants to satisfy the compiler.
- Q1269: Write a higher-order function that takes a predicate and counts matching items in a list.