This should make it more general:
template liftProc(fname) =
proc fname[T](x: openarray[T]): auto =
var temp: T
type outType = type(fname(temp))
result = newSeq[outType](x.len)
for i in 0..<x.len:
result[i] = fname(x[i])
liftProc(sin)
echo sin(@[[[1.0,2.0]],[[3.0,4.0]],[[5.0,6.0]]])
Please note that sin(aMatrix) is usually not the sin of its elements, but something different (take the Taylor-series). @andrea has a matrix library (which I haven't checked yet).
I'm not suggesting here anything, just for fun: if you find a symbol (let's say ~) which is free and sticks, then you could do things like ~sin(x) works if x is a seq[float], ~~~~sin(y) works if y is seq[seq[seq[seq[float]]]]. This could be done generally, without referring to sin when you create this macro.
Thanks. You make that look easy ;-)
Please note that sin(aMatrix) is usually not the sin of its elements, but something different (take the Taylor-series). @andrea has a matrix library (which I haven't checked yet).
Good point. The extension of these math functions to handle sequences and sequences of sequences (I was thinking) was to be a separate math library, so you have to specifically import it. That would provide some separation of namespaces.
I note that with the numpy library for python, sin() can take a single value or an array of values (and nested arrays).
I like exercises like this. We could build a page like https://www.4clojure.com/ about Nim proc, template and macro exercises.
Peter