What does EK9 error E04050 mean when I declare a class field and how do I fix it?
← Classes and OOP · Ref: Q1282
E04050 fires when you use the '<-' declaration form for a class field with an expression the compiler cannot resolve to a simple type during early phase processing. In practice the usual cause is writing the is-set operator '?' at the end of a parameterised constructor call, like 'names <- List() of String?'. That is NOT a nullable-type marker in EK9 — it is the is-set operator being invoked on the newly-created List, which produces a Boolean, which cannot be the type of a List field. The compiler reports E04050 because type inference cannot reconcile 'List of String' with 'Boolean'.
THE FIX
Drop the trailing '?' and use the simple parameterised constructor form:
names <- List() of String
This declares a class field 'names' of type 'List of String' and initialises it to an empty list. The List type is always 'set' when created, so you do not need an is-set check on it.
WHY THIS CATCHES PEOPLE
C#, Kotlin, TypeScript, and Swift all use a trailing '?' on a type to mean 'nullable'. EK9 has no null. '?' in EK9 is the is-set operator — it is a unary postfix method that returns a Boolean telling you whether the object it is called on currently holds a meaningful value. Writing 'List() of String?' therefore means 'construct an empty List, then ask whether it is set' — not 'a List field that might be unset'.
FIELD DECLARATION FORMS THAT WORK
names <- List() of String // empty List of String scores <- Dict() of (String, Integer) // empty Dict tags <- ["alpha", "beta", "gamma"] // List literal (type inferred) counters as Integer: 0 // explicit type + initial value label as String: "default" // explicit type + literal choice as String: isReady <- "a" : "b" // explicit type + ternary
FIELD DECLARATION FORMS THAT FAIL WITH E04050
Holder
isReady <- true
names <- List() of String? // ERROR E04050: '?' invoked on the List
choice <- isReady <- "a" : "b" // ERROR E04050: an EK9 ternary - write 'choice as String: isReady <- "a" : "b"'
WHEN IN DOUBT USE EXPLICIT TYPING
If the field's type is at all complex, abandon '<-' and use 'name as Type: value'. The explicit form tells the compiler the type up front and lets full expression processing happen later:
total as Float: price * quantity // explicit type survives complex expr
See Q585 for field initialisation and constructor delegation. See Q104 for why EK9 requires explicit constructors on some uninitialised fields.
Example
#!ek9 defines module qa.classesandoop.e04050fieldfix defines class UniqueNames names <- List() of String add() -> name as String if names not contains name names += name count() as pure <- rtn as Integer: length names override operator ? as pure <- rtn as Boolean: names? operator $ as pure <- rtn as String: `UniqueNames(${length names})` defines program E04050FieldFixDemo() stdout <- Stdout() names <- UniqueNames() names.add("Alice") names.add("Bob") names.add("Alice") stdout.println($names)
Common mistakes
E04050 — The trailing '?' invokes the is-set operator on the constructed List, producing a Boolean. Type inference cannot reconcile that with a List-of-String field. Drop the '?' — EK9 has no nullable types, and the List itself is always set once created.
Incorrect:
names <- List() of String?
Correct:
names <- List() of String
Other ways to ask this
- I'm getting E04050 'not expecting complex expression' on a class field — what's wrong?
- Why does 'names <- List() of String?' fail to compile in a class body?
- How do I initialize a List field in an EK9 class without E04050?
- The compiler says my field declaration needs a simple aggregate — how do I fix it?
Coming from another language?
C#/Kotlin: 'List<string>?' means nullable List — a valid type. EK9: 'List() of String?' means 'call ? on the newly-created List' — produces Boolean, fails type inference. If you want a field that might be unset in EK9, the collection itself is always set (empty List IS valid); the question 'is this field populated' is answered by '?' on the field at the point you check it, not in the type declaration.
Keywords: E04050, List, complex expression, field declaration, is-set operator, nullable type, type inference