assert not(1==2) gives compile error
the workaround is to use assert(not(1==2)) or assert(not 1==2) or (as I often see used in unittests), assert condition == false
but why this limitation?
what's weird is if I replace not but another proc with same signature it works:
# here `not` in system.nim
proc `not`*(x: bool): bool {.magic: "Not", noSideEffect.}
#here's a `not` replacement with same signature that doesn't have this issue
proc not2(a:bool):bool = a == false
proc echo2(a:bool):bool = echo a
proc test()=
# OK
echo not2 1==2
assert not2 1==2
assert not2(1==2)
when false:
# error: Error: type mismatch: got <proc (x: varargs[typed]){.gcsafe, locks: 0.}, bool>
echo not(1==2)
# Error: type mismatch: got <proc (a: bool): bool{.gcsafe, locks: 0.}, bool>
echo2 not(1==2)
assert not(1==2)
# OK
echo(not(1==2))
test()
D20180712T133436
EDIT even this patch didn't fix it:
diff --git a/lib/system.nim b/lib/system.nim
index 9e91bc7db..fb4b2d592 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -180,7 +180,10 @@ else:
## Cannot be overloaded.
discard
-proc `not`*(x: bool): bool {.magic: "Not", noSideEffect.}
+proc `==`*(x, y: bool): bool {.magic: "EqB", noSideEffect.}
+ ## Checks for equality between two `bool` variables
+
+proc `not`*(x: bool): bool = x == false
## Boolean not; returns true iff ``x == false``.
proc `and`*(x, y: bool): bool {.magic: "And", noSideEffect.}
@@ -358,8 +361,6 @@ proc `==`*(x, y: string): bool {.magic: "EqStr", noSideEffect.}
proc `==`*(x, y: char): bool {.magic: "EqCh", noSideEffect.}
## Checks for equality between two `char` variables
-proc `==`*(x, y: bool): bool {.magic: "EqB", noSideEffect.}
- ## Checks for equality between two `bool` variables
proc `==`*[T](x, y: set[T]): bool {.magic: "EqSet", noSideEffect.}
## Checks for equality between two variables of type `set`
##
#instead of : assert not 1==2
assert: not 1==2
assert: 1 != 2
assert foo != bar is also causing issues, see https://github.com/nim-lang/Nim/pull/8612#discussion_r210423399not is a keyword unary operator and "every other" proc is not a keyword unary operator.
I think this happens because during the parsing stage the compiler doesn't know if an operator is a binary or unary operator. Note that this is valid:
proc `not`(a, b: int): int = a + b
echo 1 not 2
Or even more evil:
template `not`(a, b: untyped) = discard
echo not 2 # Compiles, but doesn't do anything
so basically there's 0 practical way to fix that? if so you guys feel free to close as wontfix.
I don't know, I only wanted to say that nothing deeply concerning is going on here.
Can we add operator specifications, similar to Haskell? Sort of
operator unary not 500 # priority 500
operator leftassoc + 100
I can write proposal (mostly copying from Haskell manual) if it has meaning. For me personally, lack of priority declarations makes user-defined operators in Nim second-class citizens - I can't give my own operators priority that better fit their semantics.
I can't give my own operators priority that better fit their semantics.
Yeah, so you need to pick operator prefixes that fit the priority. I like it the way it is and Haskell's way makes parsing dependent on a symbol table, a big no-go.
@Araq my understanding how it may be implemented:
Define "flat" expression syntax:
expr ::= (operand operator)* operand
operand ::= variable | function_call | '(' expr ')' | ....
Once we parsed expression as flat list of operators/operands, parse the list using operator precedence parser. BTW, Wikipedia states:
GCC's C and C++ parsers, which are hand-coded recursive descent parsers, are both sped up by an operator-precedence parser that can quickly examine arithmetic expressions. Operator precedence parsers are also embedded within compiler compiler-generated parsers to noticeably speed up the recursive descent approach to expression parsing.
You don't have to explain these things to me, I know how it can be implemented. And I don't like it.
assert not(1==2)gives compile error
the workaround is to use
assert(not(1==2))orassert(not 1==2)
I just found another workaround: assert (1==2).not
(BTW: assert(not 1==2) doesn't work. Maybe something was changed in the mean time.)
assert(not expr) works in general, but assert(not 1==2) is equivalent with assert(not(1)==2) due to not and == having the same operator precedence.
Well, almost, not binds tighter because unary binds tighter than binary.
Well I don't see an issue here anymore. The not(1==2) problem is solved by using the != operator, ithas a generic implementation that works with all types that have an == operator. The claim that assert foo != bar gives a compile error is an invalid statement.
I hope all questions about the prefix operator not could be resolved.
Well I don't see an issue here anymore.
That's probably because you're focusing only on the provided example, and not the general case:
proc isFalse(a: int): bool = false
assert not isFalse(3) # doesn't work
assert not(isFalse(3)) # doesn't work
As much as I love closing issues, I think this one might be prematurely closed, so I'm reopening it.
I reworked the issue in a more compact representation, therefore I am closing this as noted. But as far as I can tell, this is just a language quirk that is not going to be fixed any time soon.
Well we can decide that not is special and always only an unary operator. That would fix it and no code out there uses an overloaded binary not operator anywhere, I guess.
Oh sorry, I just saw you opened a different bug for this.
/cc @krux02
The claim that assert foo != bar gives a compile error is an invalid statement.
as I had mentioned in top-post, it gives compile error in some cases, see https://github.com/nim-lang/Nim/pull/8612#discussion_r210423399
EDIT: that particular point must've been fixed since that was reported (used to be a valid statement, not anymore)
Most helpful comment
That's probably because you're focusing only on the provided example, and not the general case:
As much as I love closing issues, I think this one might be prematurely closed, so I'm reopening it.