Code below won't work, but if type restriction J: Job removed and just the J used it works. How to fix that?
type
Job = object of RootObj
id: string
Container[J: Job] = object
job: J
GetPriceJob = object of Job
message: string
discard Container[GetPriceJob]()
because you specifically restricted Container to only accept Job. terrible error message, yikes.
you'd need to
type
Job = object of RootObj
id:string
GetPriceJob = object of Job
message:string
Container[T:Job | GetPriceJob] = object
job: T
or
type
Job = ref object of RootObj
id:string
GetPriceJob = ref object of Job
message: string
Container = object
job:Job
Thanks, but I'm not sure I can do that, the Container is declared before and in separate module than the GetPriceJob, so this Container[T:Job | GetPriceJob] declaration is impossible.
The real example - I'm building a Crawler that should handle different types of Jobs. There's the lib/crawler module and everyone can use it if it declares the proc process[J: Job](job: J): void function. So the specific type like GetPriceJob is declared after, it's unknown to the lib/crawler module.
The unexpected thing is that it actually works if no type restriction is used. The whole example, play with it online https://repl.it/@alexeypetrushin/crawler#main.nim
Code for lib/crawler.nim
type
Job* = object of RootObj
id*: string
CrawlerRef*[J] = ref object
job: J
proc new_crawler*[J](job: J): CrawlerRef[J] =
CrawlerRef[J](job: job)
proc run*[J](crawler: CrawlerRef[J]): void =
# Why this version won't work?
# let v: string = process(crawler.job)
let v: string = crawler.job.process()
echo crawler.job.id, "=", v
Code for main.nim
import lib/crawler
type GetStockPrice = object of Job
value: string
proc process(job: GetStockPrice): string =
job.value
var price_crawler = new_crawler(
job = GetStockPrice(id: "MSFT", value: "500USD")
)
price_crawler.run()
Thanks, but I'm not sure I can do that, the Container (The is declared before and in separate module than the GetPriceJob, so this Container[T:Job | GetPriceJob] declaration is impossible.
You are asking a compiler with a static type system to accept a type definition with a value memory size unknown at compile time. This is not possible. You probably want one of these:
This is not possible
But it is possible, this code works in Nim
type
Job = object of RootObj
id: string
Container[J] = object # <== J type
job: J
GetPriceJob = object of Job
message: string
discard Container[GetPriceJob]()
My question was - why it stop working if I require that not all objects could be used as J type, but only subclasses of Job class. And use Container[J: Job] to tell Nim about that restriction.
And it stop working. That doesn't make sense.
Yep, looks like a bug. You found the workaround there though: make your own constructor
proc newContainer[T:Job](j:T):Container[T] =
result.job = j
This can be achieved with concepts, a generic way I've found is this.
type Subtype[T] = concept st
st of T
type Container[J: Subtype[Job]] = object
job: J
discard Container[GetPriceJob]() # works
discard Container[int]() # doesn't work