E08273: word 'not' is never an operand of another operator unless parenthesised, except 'and', 'xor' and 'or' - it binds below the comparisons, so write 'a == (not b)' or '$ (not b)', or 'not (a == b)' if that is meant; 'a and not b' needs none
What went wrong
Word 'not' is never an operand of another operator unless parenthesised, except 'and', 'xor' and 'or'. Here it is an operand of an operator that binds tighter than it, with no parentheses. Word 'not' binds below the comparisons, like Python and SQL, so on the LEFT it takes the whole comparison: 'not ready == done' is 'not (ready == done)'.
Read from the right, the same rule would make 'ready == not done' mean 'ready == (not done)' - a 'not' that does NOT reach past the '==' before it. The two places read differently, so EK9 (like Python) does not accept the second without parentheses: 'ready == not done' is this error.
The operators this applies to are every binary operator except 'and', 'xor' and 'or': '^', the coalescing operators '?:' '<?' '>?', '*' '/' 'mod' 'rem', '+' '-', '<<' '>>', '<=>' '<~>', '<' '<=' '>' '>=', 'matches', 'contains', 'in' (and their 'not' forms, and the start of 'x in a ... b'), and '==' '<>' '!='.
It applies to every PREFIX operator as well: '$$', '$', '#^', 'length', '#<', '#>', '#?', 'abs' and 'sqrt'. Each binds tighter than word 'not', so '$ not done' would be '$ (not done)' while 'not done == ready' is 'not (done == ready)' - the same trap written the other way round. Parenthesise the negation: '$ (not done)'. The exception is '~not done' and '-not done': '~' and unary '-' are themselves negations (the same operator as 'not'), so each is a negation of a negation (E08274) and parentheses would not mend it - '~(not done)' is E08274 too.
Worked examples
Compilable examples demonstrating this error and the correct fix:
- ek9 -q 2160 (What is EK9's operator precedence - does 'and' bind tighter than 'or', and where does 'not' sit?)
Each of these is E08273 ('~not done' and '-not done' are E08274 instead, a negation of a negation):
- same <- ready == not done
- under <- low < not high
- chosen <- flag ?: not other
- found <- ready in not wanted
- text <- $not done //a prefix operator
Each of these is fine:
- //Negate only the right operand
- same <- ready == (not done)
- //Negate the comparison (also written 'not ready == done')
- different <- not (ready == done)
- //'and', 'xor' and 'or' bind below 'not': one reading only
- both <- ready and not done
- either <- ready or not done
- //A prefix operator over a parenthesised negation
- text <- $ (not done)
- //'~' is the tight negation: no parentheses needed
- tight <- ready == ~done
How to fix it
- Parenthesise the negation to negate only that operand: 'ready == (not done)', '$ (not done)'.
- Or, if the whole comparison was meant to be negated, say so: 'not (ready == done)', or use the opposite operator: 'ready <> done'.
- '~' is the tight negation: 'ready == ~done' is 'ready == (~done)' with no parentheses needed.
Common causes
- Writing 'a == not b' expecting 'a == (not b)', as C's '!' would give
- Writing 'x < not y' while meaning 'not (x < y)'
- Writing '$ not flag' or '#? not flag' to convert or hash the negation
- Translating Python's 'a == (not b)' and dropping the parentheses
See also
- E08273: word 'not' as an operand of another operator (this error)
- E08269: a coalescing operator mixed with another operator without parentheses
- E08274: a negation applied to a negation ('not not b', '~not b', '-not b', 'not (not b)')
- E07620: an operator ('~' / 'not' included) that the operand's type does not define
Examples
Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.
Fails with E08273: word 'not' is never an operand of another operator unless parenthesised, except 'and', 'xor' and 'or' - it binds below the comparisons, so write 'a == (not b)' or '$ (not b)', or 'not (a == b)' if that is meant; 'a and not b' needs none
#!ek9 defines module error.e08273.bad defines function sameAsNot() -> ready as Boolean done as Boolean <- rtn as Boolean? rtn: ready == not done otherForms() -> ready as Boolean done as Boolean low as Boolean high as Boolean flag as Boolean other as Boolean wanted as List of Boolean same <- ready == not done under <- low < not high chosen <- flag ?: not other found <- ready in not wanted text <- $not done //a prefix operator
Fixed: Parenthesise the not - or the comparison, if that is what is meant
#!ek9 defines module error.e08273.good defines function sameAsNot() -> ready as Boolean done as Boolean <- rtn as Boolean? rtn: ready == (not done) notSame() -> ready as Boolean done as Boolean <- rtn as Boolean? rtn: not (ready == done)
Fixed: Parenthesise the negation, negate the whole comparison, or use 'and'/'or'
#!ek9 defines module error.e08273.good.forms defines function readings() -> ready as Boolean done as Boolean <- rtn as String? //Negate only the right operand same <- ready == (not done) //Negate the comparison (also written 'not ready == done') different <- not (ready == done) //'and', 'xor' and 'or' bind below 'not': one reading only both <- ready and not done either <- ready or not done //A prefix operator over a parenthesised negation text <- $ (not done) //'~' is the tight negation: no parentheses needed tight <- ready == ~done rtn: `${same} ${different} ${both} ${either} ${text} ${tight}`
Questions and answers
These Q&A entries show E08273 and its fix: