Hi Im making a discord invite checker, it returns a custom type called "Guild", but while spawning the procedure the compiler complains:
Error: cannot create a flowVar of type: Guild
Here is the code:
import json, httpclient, threadpool, strformat
type
Guild = object
name: string
desc: string
inviter_name: string
inviter_discrim: string
channel: string
var guilds: seq[Guild]
proc check(code: string): Guild {.thread.} =
let client = newHttpClient()
let content = client.get(&"https://discord.com/api/v9/invites/{code}")
if content.status == "200 OK":
let json_content = parseJson(content.body)
let
guild_name = json_content["guild"]["name"].getStr()
guild_welcome_desc = json_content["guild"]["welcome_screen"]["description"].getStr()
guild_inviter_name = json_content["inviter"]["username"].getStr()
guild_inviter_descrim = json_content["inviter"]["discriminator"].getStr()
guild_invite_channel = json_content["channel"]["name"].getStr()
result = Guild(name: guild_name, desc: guild_welcome_desc, inviter_name: guild_inviter_name, inviter_discrim: guild_inviter_descrim, channel: guild_invite_channel)
let some_guild = spawn check("gtyt4zido")
guilds.add(some_guild)
Thanks for your help
Using async instead of threads might be a better approach but you can try compiling with --gc:arc and changing:
guilds.add(some_guild)
to
guilds.add(^some_guild)
fyi im no expert with Nim threading so take it with a grain of salt.
What @xioren said: spawn returns a FlowVar and you have to wait for it to get your type.
As to your reading from nil, you have never constructed the ref which allocates it on the heap so it's still nil - you can't deal with reference objects the same way as value objects just as in other languages you need to "new up" a reference.
Nim threading (and also async as was suggested) are in a state of flux right now as we move to the new memory management models of Arc/Orc: the old FlowVar's in the threadpool library are very restrictive as to the types with which they work as are the arguments passed to spawn (see the section in the experiment part of the manual); a new threadpool library built to work with the new memory management doesn't exist yet and I am in process of writing it.
The work around for now if you need to pass variables not compatible with FlowVar/spawn is to create pointers to the incompatible types and use those dereferenced. Messy, which is why we are moving away from it.
For the logic I knew it, Im now looking for a better way of implementing that. I would like to use async instead but I never managed to understand how to use it, even in other languages like python Hope the threading will get better with time
Thanks for your help
One way you could implement async:
import json, httpclient, asyncdispatch, strformat
type
Guild = object
name: string
desc: string
inviter_name: string
inviter_discrim: string
channel: string
var guilds: seq[Guild]
proc check(code: string): Future[Guild] {.async.} =
let client = newAsyncHttpClient()
let content = await client.get(&"https://discord.com/api/v9/invites/{code}")
if content.status == "200 OK":
let json_content = parseJson(content.body.read)
let
guild_name = json_content["guild"]["name"].getStr()
guild_welcome_desc = json_content["guild"]["welcome_screen"]["description"].getStr()
guild_inviter_name = json_content["inviter"]["username"].getStr()
guild_inviter_descrim = json_content["inviter"]["discriminator"].getStr()
guild_invite_channel = json_content["channel"]["name"].getStr()
result.name = guild_name
result.desc = guild_welcome_desc
result.inviter_name = guild_inviter_name
result.inviter_discrim = guild_inviter_descrim
result.channel = guild_invite_channel
let some_guild = waitFor check("gtyt4zido")
guilds.add(some_guild)