I am wrote the following three files. There are two objects ModInt and FormalPowerSeries. FormalPowerSeries has generics T and it takes ModInt. Both objects has proc named pow. Pow is called from FormalPowerSeries and in the proc, it also call pow of generics T.
test.nim:
import modint
import formal_power_series
var v = FormalPowerSeries[ModInt](data: @[ModInt()])
echo v.pow(2)
formal_power_series.nim:
#import modint
type FormalPowerSeries*[T] = object
data*:seq[T]
proc pow*[T](self:FormalPowerSeries[T], k:int):auto=
@[T().pow(k)]
modint.nim:
type ModInt* = object
a*:int
proc pow*(a:ModInt, k:int):ModInt = a
Then, I compiled test.nim, getting error that
Error: type mismatch: got <ModInt, int>
but expected one of:
proc pow[T](self: FormalPowerSeries[T]; k: int): auto
first type mismatch at position: 1
required type for self: FormalPowerSeries[pow.T]
but expression 'T()' is of type: ModInt
expression: pow(T(), k)
It seems that the function pow of T(=ModInt) is not recognized. But I know that changing the proc name "pow" of ModInt to any other name and making these proc different works. I also know that inserting a line "import modint" (which is commended out now) to formal_power_series.nim works. But it is not prefered because I want to make the object FormalPowerSeries abstruct i.e. it works any object T which has proc pow.
Are there any way to avoid error?
This should do the job:
proc pow*[T](self:FormalPowerSeries[T], k:int):auto=
mixin pow
@[pow(T(), k)]
If your intention is for pow to be overloaded, you can declare it an "open symbol" with the mixin statement
like this:
type FormalPowerSeries*[T] = object
data*: seq[T]
proc pow*[T](self: FormalPowerSeries[T], k: int): auto =
mixin pow
@[T().pow(k)]
this causes dispatch to be delayed until instantiation.
Thanks! I should learn mixin statement and open and closed symbol. Do you refer to the following?
https://nim-lang.org/docs/manual.html#symbol-lookup-in-generics-open-and-closed-symbols
I read it several time but I couldn't understand what "open symbol" is.
open means a symbol can refer to something that didn't exist at the time the symbol was defined
in your case, Modint doesn't exist within formalpowerseries.nim, and pow can only refer to the pow in that file, that's the "context at definition"
when we make pow an open symbol, it also takes into account the "context at instantiation", i.e. within test.nim, where Modint and pow(Modint,int) exist.
Does it pose a potential security risk by means of code injection?
Depends on what you mean by "security". IMO not it doesn't, because you can always call the wrong function and produce a bug.
But it depends on your definition of "security". For example, for my definition of security: An OS that allows every process by default to read all of /home/araq and to upload the files to a distant server has no "security".
Is this a similar issue? I can't define operator < even if I insert mixin statement.
import heapqueue
proc main() =
type Q = object
d:int
mixin `<`
proc `<`(a, b:Q):bool = a.d < b.d
var q = initHeapQueue[Q]()
for d in [3, 1, 4, 1, 5, 9, 2, 6, 5]:
q.push(Q(d:d))
while q.len > 0:
var a = q.pop()
echo a.d
main()
import heapqueue
type Q = object
d:int
#mixin `<`
proc `<`(a, b:Q):bool = a.d < b.d
proc main() =
var q = initHeapQueue[Q]()
for d in [3, 1, 4, 1, 5, 9, 2, 6, 5]:
q.push(Q(d:d))
while q.len > 0:
var a = q.pop()
echo a.d
main()
Thanks @Araq and @Stefan_Salewski.
For now, heapqueue doesn't support custom comparison function. It only allows <. It is very inconvenient...