How do these work? I don't see them mentioned in the documentation. I did try something like this:
type
Vector3*[T] = concept V
V.x is var T
V.y is var T
But later attempts to use Vector3[int] failed saying I had supplied the typedesc[int] instead.
type
Vector3*[T] = concept var v
v.x is var T
v.y is var T
v.z is var T
proc doThing(v: Vector3[int]) = echo v
doThing (x: 100, y: 200, z: 400)
Although V.x is var T did work in my testing this is likely a more appropriate way to write it.thank you. i tried it and now it is working. previously it was giving odd issues about function signatures not being present even though the struct had those fields.
i guess i was confused because var typically means variable and in the setters i did not use var because i was trying to match the usual setter(self: var T; neu: K) signature and so K was not "var."
something about concepts seems to be er. somewhat a random break from what things in nim code usually mean.
I did note using concepts as return values gives errors about typeof(result.x), so it's not seemingly possible to organically chain functions across disparate math types. Can be solved by having out parameters, but does make the API er.
Weird to use.
As a forewarning: Concepts are one of the more experimental (and less functional) features in Nim. They have long been known to lead to exponential compile times, code-gen malfunctions, and more. But for simple cases, they're great.
It's generally good form to define return types inside the concept like:
type GenericMultiplier = concept x
x * x
type Resultant = typeOf(x * x)
func doMultiplication(a, b: GenericMultiplier): a.Resultant =
a * b
assert doMultiplication(5, 10) == 50
type ChainableMultiplier = concept x
x is GenericMultiplier
(x * x) is GenericMultiplier
func doChainMultiplication(a, b: ChainableMultiplier): ChainableMultiplier =
a * b
assert doChainMultiplication(5, 10).doChainMultiplication(10) == 500
Which can be done in the generic type parameter declaration, as @ElegantBeef pointed out.