https://github.com/nim-lang/Nim/blob/a8b53c97ee041bc02862b17a6b7cf70546979a6e/lib/system.nim#L3836
https://github.com/nim-lang/Nim/blob/a8b53c97ee041bc02862b17a6b7cf70546979a6e/lib/system.nim#L724
Not sure which one is the right one, but this causes several problems when trying to figure out which one to use:
inc, as specified, requires that 'y' is an int even when T is something else - from what I remember of the C gen it just sprinkles NI casts liberally which might be surprising if you want to inc a uint8Ordinal actually and why doesn't it include uint64? why does += include uint64 but Ordinal does not?SomeOrdinal and how is it different from Ordinal?@arnetheduck It is the same, except that it includes enums with holes.
https://github.com/nim-lang/Nim/blob/a8b53c97ee041bc02862b17a6b7cf70546979a6e/lib/system.nim#L99
I really really wish += (et al) would work for any type that has a + operation defined. I really really don't want to define inc, +=, +, and the same for *, -, / every time I create a new type.
I feel like I've mentioned this multiple times now. Can we please fix this in a generic way once and for all?
@Clyybber yeah, I know what the definitions in Nim are - by _why_ do both exist / what's the intent? Or from a user perspective, when would I use one over the other?
@dom96 That's a different issue and the reply still is "it's way more efficient to express + in terms of += than the other way round".
To answer the question, inc is for incrementing an ordinal with an integer, for example var x = january; inc x, 2; assert x == march
x += y is the usual shortcut for x = x + y
@dom96 That's a different issue and the reply still is "it's way more efficient to express + in terms of += than the other way round".
With concepts couldn't it be done both ways? Implement + using += if only += exists, implement += using + if only + exists, implement nothing if neither or both exists.
@dom96 @GULPF Placing this in system.nim works perfectly, as far as my testing goes:
Addable = concept x, y
(x + y) is x.type
Subtractable = concept x, y
(x - y) is x.type
Multipliable = concept x, y
(x * y) is x.type
Dividable = concept x, y
(x / y) is x.type
proc `+=`*(x: var Addable, y: Addable) {.noSideEffect.} =
## Increments anything
x = x + y
proc `-=`*(x: var Subtractable, y: Subtractable) {.noSideEffect.} =
## Decrements anything
x = x - y
proc `*=`*(x: var Multipliable, y: Multipliable) {.noSideEffect.} =
## Multiplies anything
x = x * y
proc `/=`*(x: var Dividable, y: Dividable) {.noSideEffect.} =
## Divides anything
x = x / y
@Araq Are we ready to use concepts in the stdlib/system.nim?
@Clyybber we need to be more subtle here: define += if it does not exist, but + does, and viceversa
@andreaferretti Yeah, I left out the viceversa part, because I'm not sure if "it's way more efficient to express + in terms of += than the other way round" applies to types not supplied by the compiler.
You don't even need concepts here as far as I can tell. Concepts are just a refinement of generics, you can easily create a generic proc for this:
proc `+=`*[T, Y](x: var T, y: Y) =
x = x + y
And it will work as long as there is a + defined on the type.
Personally I'm still not comfortable having concepts in the stdlib and they don't really add that much here IMO.
@dom96 That's a different issue and the reply still is "it's way more efficient to express + in terms of += than the other way round".
It's way more efficient to just get the "good enough" solution which is what I've suggested above, than to make everything efficient. Having hundreds PRs which add these noisy procedures is a waste of time.
Also, I think the ship to get people to define += instead of + has sailed by now.
It took me a while as well to understand the difference. In my code I always used += while the standard library really prefers inc over +=.
Even though both inc and += do practically exactly the same, the concept is a bit different. The idea behind inc is to increment anything. This includes enum values. The offset is then specified by an integer, but it thas the default to 1. So inc is really made for while loops and iterators, while += is really meant for addition where both argument types are the same. This won't work for enums as adding two enum values doesn't really work.
I hope I could clear the question. I am closing this issue now though as it is more a question rather than a real issue description.
Most helpful comment
With concepts couldn't it be done both ways? Implement
+using+=if only+=exists, implement+=using+if only+exists, implement nothing if neither or both exists.