Hello,
I would like to write a function that will take an input and perform a processing and depending on the result it should output an object of a particular type.
The procedure is more complicated, but the example below shows what I want to do.
What method do you recommend to succeed?
Thanks.
type
V2*[T: SomeInteger] = object of RootObj
a*, b*: T
V3*[T: SomeInteger] = ref object of V2[T]
c*: T
V4*[T: SomeInteger] = ref object of V3[T]
d*: T
V*[T] = V2[T] | V3[T] | V4[T]
proc my_return[T](dim: int): V =
if dim == 1:
return V2[T](a: 0, b: 1)
elif dim == 2:
return V3[T](a: 0, b: 1, c: 3)
elif dim == 3:
return V4[T](a: 0, b: 1, c: 3, d: 4)
else:
return V2[T](a:0, b:0)
echo my_return[int](1) # want a V2[int](a: 0, b: 1)
echo my_return[int](2) # want a V3[int](a: 0, b: 1, c: 3)
echo my_return[int](3) # want a V4[int](a: 0, b: 1, c: 3, d: 4)
try this:
type #V2 has to a ref object
V2*[T: SomeInteger] = ref object of RootObj
a*, b*: T
V3*[T: SomeInteger] = ref object of V2[T]
c*: T
V4*[T: SomeInteger] = ref object of V3[T]
d*: T
method `$`[T](a : V2[T]) : string {.base.} =
$a[]
method `$`[T](a : V3[T]) : string =
$a[]
method `$`[T](a : V4[T]) : string =
$a[]
proc my_return[T](dim: int): V2[T] =
if dim == 1:
return V2[T](a: 0, b: 1)
elif dim == 2:
return V2[T](V3[T](a: 0, b: 1, c: 3))
elif dim == 3:
return V2[T](V4[T](a: 0, b: 1, c: 3, d: 4))
else:
return V2[T](a:0, b:0)
echo my_return[int](1) # want a V2[int](a: 0, b: 1)
echo my_return[int](2) # want a V3[int](a: 0, b: 1, c: 3)
echo my_return[int](3) # want a V4[int](a: 0, b: 1, c: 3, d: 4)
I would use one of our vector math libraries, for example
Such a reply is similar as to suggest just using Julia or Rust instead of Nim :-(
Unfortunately I have to admit that I do not really understand the issue. Even with "dim: static[int]" and "when dim == 1:" it gives for me
cannot instantiate: 'my_return[int]'; got 1 typeof(s) but expected 2
which I have no idea about.
Of course his code is really strange, as V2 is a value object and the others are ref objects.
Well, it boils down to:
type
V2*[T: SomeInteger] = object of RootObj
a*, b*: T
V3*[T: SomeInteger] = ref object of V2[T]
c*: T
proc my_return[T](dim: int): V3[T] =
return V3[T](a: 0, b: 1, c: 3)
echo "done"
echo my_return[int](1)
If you want to get it "done", outcomment the echo stmt below.
Of course his code is really strange, as V2 is a value object and the others are ref objects.
That's not the problem here.
If you wanted to do it statically you could do it like this:
type #V2 has to be a ref object
V2*[T: SomeInteger] = ref object of RootObj
a*, b*: T
V3*[T: SomeInteger] = ref object of V2[T]
c*: T
V4*[T: SomeInteger] = ref object of V3[T]
d*: T
proc `$`[T](a : V2[T]) : string =
$a[]
proc `$`[T](a : V3[T]) : string =
$a[]
proc `$`[T](a : V4[T]) : string =
$a[]
proc my_return[T](dim: static[T]): auto =
when dim == 1:
return V2[T](a: 0, b: 1)
elif dim == 2:
return V3[T](a: 0, b: 1, c: 3)
elif dim == 3:
return V4[T](a: 0, b: 1, c: 3, d: 4)
else:
return V2[T](a:0, b:0)
echo my_return(1) #with explicit parameters needs to be called like this
#echo my_return[int,1](1)
#since static implicitly introduces another static parameter
echo my_return(2)
echo my_return(3)
or like this:
type #V2 has to be a ref object
V2*[T: SomeInteger] = ref object of RootObj
a*, b*: T
V3*[T: SomeInteger] = ref object of V2[T]
c*: T
V4*[T: SomeInteger] = ref object of V3[T]
d*: T
proc `$`[T](a : V2[T]) : string =
$a[]
proc `$`[T](a : V3[T]) : string =
$a[]
proc `$`[T](a : V4[T]) : string =
$a[]
proc my_return(T : type[SomeInteger], dim: static[int]): auto =
when dim == 1:
return V2[T](a: 0, b: 1)
elif dim == 2:
return V3[T](a: 0, b: 1, c: 3)
elif dim == 3:
return V4[T](a: 0, b: 1, c: 3, d: 4)
else:
return V2[T](a:0, b:0)
echo my_return(int,1)
echo my_return(int,2)
echo my_return(int,3)
Would an array or a seq not work?
Exactly. Modeling vectors via inheritance is simply wrong.
I would do something like this:
type
VecLen = enum
vecLen2
vecLen3
vecLen4
V*[T] = object
case n: VecLen
of vecLen2: v2: array[2, T]
of vecLen3: v3: array[3, T]
of vecLen4: v4: array[4, T]
proc my_return[T](dim: int): V[T] =
if dim == 1:
return V[T](n: vecLen2, v2: [0, 1])
elif dim == 2:
return V[T](n: vecLen3, v3: [0, 1, 2])
elif dim == 3:
return V[T](n: vecLen4, v4: [0, 1, 2, 3])
else:
return V[T](n: vecLen2, v2: [0, 0])
echo my_return[int](1) # want a V2[int](a: 0, b: 1)
echo my_return[int](2) # want a V3[int](a: 0, b: 1, c: 3)
echo my_return[int](3) # want a V4[int](a: 0, b: 1, c: 3, d: 4)
Thanks everyone.
Maybe, I should added a disclaimer: "i'm trying several techniques in nim, some bad, some wrong, etc".
Some responses:
I would use one of our vector math libraries, for example https://github.com/mratsim/Arraymancer
Arraymancer is a very good library, but it's out of the purpose here.
> Would an array or a seq not work?
Exactly. Modeling vectors via inheritance is simply wrong
I'm trying several approaches, seq/array or like @doofenstein solution.
My question was purely technical. Thanks @Sixte and @solo989