proc `+`(x,y: int): int =
return x + y
Calling that binary operator is then one of
var a = 3 + 4
var b = `+`(3,4)
The docs are pretty clear on the characters allowed for user operators at http://nimrod-lang.org/manual.html#operators. So defining something like this
proc `fred` (x, y: int): int =
return x + y + 100
Can be called as
var c = fred(3,4)
or even
var c = `fred` (3,4)
but not
var c = 3 fred 4
since the word fred is not composed of the defined operator characters. So I'm surmising that the backquotes serve as an escape for the parser, keeping the term from being evaluated at compile-time and thus can be used in any context where you don't want the compiler from parsing the input (useful in lisp/scheme macros if memory serves correctly). Is this the intended meaning of the backquote?
On a related note, doing something like this currently compiles:
proc `+`(x, y: int): int =
return x + y + 1000
var c = 3 + 4 # expecting 1007
But when run, it terminates with exit code 1 at the offending addition. Now I really don't think you should be able to override a primitive with primitive types like this, but it looks like you can successfully override some of the other built-in system procedures. The following works fine:
proc len(x: string): int =
return 100
var sa = "I am a string"
echo "sa=", sa, " new_len=", len(sa), " system_len=", system.len(sa)
# returns sa=I am a string new_len=100 system_len=13
This case makes a bit more sense than attempting to override the addition function (I've only seen that behaviour from Smalltalk) - but where is the intended dividing line; what are the rules for what can be overridden and what is 'primitive'? Perhaps if it magic (compiler-derived) or not (compiled)?
proc `+`(x, y: int): int {.noSideEffect.} =
return system.`+`(system.`+`(x, y), 1000)
var c = 3 + 4 # expecting 1007
echo c
Wow, so it does. Very clear from the code as to why, thanks - hadn't thought through the scoping implied by such a statement.
So I suppose it's safe to assume that either by design or happenstance one can override any of the primitive operators in such a way (quick experimentation suggests yes)? Really don't see any reason to do such a thing (and many, many reasons not to) outside of perhaps a temporary bug workaround in the system libraries. I would think such general behaviour may make the compiler optimizations a bit harder, but I haven't looked into how the compiler works in enough detail to get a sense one way or another.
I got looking into this in the first place by exploring why two integers divided produced a float result - no problems or complaints with the implementation ( / only defined for floats, need to use div operator for integer division - the docs and system.nim file are exceptionally easy to read through), just not what I would have expected. If for some reason I didn't like that behaviour, it's trivial to implement:
proc `/`(x, y: int): int {.noSideEffect.} =
return x div y
var dd = 123 / 17
echo dd
though the implementation as is makes floating and integer division clear and certainly seems like the right way to go.
This looks like a regression to me. It's not just operators either:
proc add(x: var string, y: string) = nil
var y = "asd"
y.add("notFoo")
echo y
And the following code even crashes:
proc add(x: var string, y: string) =
x.add("foo")
var y = "asd"
y.add("notFoo")
echo y
The compiler should force you to specify which add proc you want to use, the one defined in your module or the one defined in system.nim. I think this deserve an issue on github.
system.add(x,"foo")
inside new proc.
Thanks for the reply. Sounds quite clear. These crashes are trivial edge cases that shouldn't be used in the first place - the add crash was recursively calling itself; I expect it ran out of stack space quickly; it should crash or do something similar. I remain pleasantly surprised this stuff works as well as it does with minimal restrictions.
Not being able to redefine the = operator is made very clear in several places, as is the fact that things are not finished to the level desired. If everything was done perfectly, there wouldn't be any work left to do - and what fun would that be?
On the topic of the backquote; is it intended as a general purpose "have the compiler or preprocessor ignore this" sort of like a quasiquote in lisp/scheme? It's one of the few pieces of syntax that I couldn't find discussion on it's purpose.
http://www.r6rs.org/final/html/r6rs/r6rs-Z-H-14.html#node_sec_11.17
The backquote is neither, it's only used for identifier construction or changing how operators are parsed:
`+`(a, b) same as a + b +(a, b) passes the tuple (a, b) to +
For quasi-quoting use inner templates and getAst or macros.quote or parseExpr.