E08096: an operator that keeps an unset value unset can never give it a value
What went wrong
An in-place operator is applied to a value that is always unset at this point, and the operator is one that keeps an unset value unset - so the operation can never give it a value. Data flow analysis proves both: the value is unset here (it was made by a no-argument constructor such as 'Integer()' or 'String()', or this code is inside 'if not x?'), and '+=', '-=', '*=', '/=', '++' and '--' on the built-in types never set an unset value, whatever the argument. The program would run and quietly leave the value unset.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 2253 (Why is 'count <- Integer()' then 'count++' reported as an ...)
- ek9 -q 2251 (How do I build up a String with '+=' in EK9?)
- ek9 -q 2252 (What should a counter or a running total start from in EK9?)
Rationale
EK9 values are tri-state: absent, present but unset, or set. 'Integer()' and 'String()' make a value that is PRESENT but UNSET - it has no value yet, not even 0 or "". An operator on an unset value gives an unset result rather than guessing, and '+=' is no exception: there is no starting value to add to, and the operator never invents one. So a total started from 'Integer()' stays unset however many amounts are added, and a sentence started from 'String()' loses every word.
This is reported only when the compiler is SURE. EK9 has no warnings, so an error must be certain: a value that came from a function call may be set, and the compiler stays silent; inside a loop the value must stay unset on every pass (a loop that also assigns it is left alone); an operator of your own type defines its own meaning and is never reported. A copy ':=:' does set an unset value, and a stream into a variable ('cat items > total') works differently again - neither is one of these operators.
How to fix it
- Start the value from a literal, which is set: a String from "", a count or a sum from 0, a product from 1, a Float from 0.0, a Duration from PT0S, a Millisecond from 0ms.
- Inside 'if not x?' give it a value with ':=' instead; the condition itself makes the value unset there, so adding to it can do nothing (assign-if-unset there always applies, E08097).
- If the value is meant to stay unset until something real arrives, assign that value when it does instead of adding to the unset one.
Common causes
- 'text <- String()' then 'text += word' to build up a String - start from ""
- 'total <- Integer()' then 'total += amount' in a loop - start from 0
- 'count <- Integer()' then 'count++' - start from 0
- A returning variable declared '<- rtn as String: String()' and then appended to
- Adding to a value inside 'if not x?', the one place it is known to be unset
See also
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08096: an operator that keeps an unset value unset can never give it a value
#!ek9 defines module error.e08096.bad defines function joinWords() -> words as List of String <- sentence as String: String() for word in words sentence += word
Fixed: Start from a value, or give the value one first
#!ek9 defines module error.e08096.good defines function //Start from a literal: '""' and '0' are set, so '+=' and '++' build on them. describe() -> words as List of String <- summary as String: "" count <- 0 for word in words summary += word count++ summary += ` (${count} words)` //An unset value is given one first - inside 'if not total?' it is unset, so ':=' is the form. topUp() -> amount as Integer <- total as Integer: amount if not total? total := 0 total += 1 //A value from a function call may be set: the compiler cannot be sure, so it stays silent. supplied() <- rtn as Integer: 1 addToSupplied() <- total as Integer: supplied() total += 1
Fixed: Start the String from "" so '+=' has a value to add to
#!ek9 defines module error.e08096.good.fix defines function joinWords() -> words as List of String <- sentence as String: "" for word in words sentence += word
Questions and answers
These Q&A entries show E08096 and its fix: