I'm trying to make a generic Spline type for my splines in NumericalNim and the behavior I want is that all splines should have a eval proc acting on a single float. What I then wanted was to just write one proc that works for all splines that instead act on a seq[float] and uses the individual splines' eval procs in a for loop. At first I hard coded my splines like this:
type
SplineType*[T] = CubicSpline[T] or HermiteSpline[T] # Here
CubicSpline*[T] = ref object
X: seq[float]
high: int
len: int
coeffs: seq[array[5, float]]
HermiteSpline*[T] = ref object
X: seq[float]
high: int
len: int
Y: seq[T]
dY: seq[T]
proc eval*[T](spline: CubicSpline[T], x: float): T =
.......
proc eval*[T](spline: HermiteSpline[T], x: float): T =
.......
proc eval*[T](spline: SplineType[T], x: openArray[float]): seq[T] =
result = newSeq[T](x.len)
for i, xi in x:
result[i] = eval(spline, xi)
This compiles and works as expected when I call the eval proc with a seq[float]. But I want this to work on any Spline I or the user creates in the future so I found concepts which seemed to fit my needs. But I can't get it to compile :/ Rather, it never finishes. It feels like it is in some kind of infinite loop or something. The way I tried to use concepts was this:
type
SplineType*[T] = concept s
s.eval(float) is T
To test this out replace this line with the above concept and then run the test file for interpolate.
I would very much appreciate any help I could get on this matter :-)
Thank you! :-) So it is a bug then. I'll try to boil it down to a more minimal example before I file an issue on Github.
Wasn't generic methods depreciated a while back? :/
They are strongly discouraged.
The most resilient way is probably to store your proc/method in a field and do the dynamic dispatch yourself, see Backward here: https://github.com/mratsim/Arraymancer/blob/2c89da87/src/autograd/autograd_common.nim#L85-L96
How would you go about accessing the other variables of the Node in your case? When you call the backward proc you would have to do something like this right?:
node.backward(node.gate, node.payload)
Could that be shortened down to something that resembles node.backward()? A template could work I'd guess, something along the lines of:
template eval*[T](spline: SplineType[T], x: float): untyped =
spline.handler(spline.X, spline.coeffs, x)
template eval*[T](spline: SplineType[T], x: openArray[float]): untyped =
spline.handler_seq(spline.X, spline.coeffs, x)
Could this work or did you have anything different in mind? :-)Yes, either you use a template or if your object carries all the required data your handler can just have the type
type Handler = proc(obj: MyObj) {.nimcall.}
Ahh, yes that is more convenient then passing all the fields manually!
Thank you very much for the help :-D