I'm trying to write a proc that returns the same integer ID, when called with the same type, from any thread (ID can change on every run). Since, AFAIK, I cannot hold/store a typedesc, I thought I would use it's name (or, more precisely, a cstring of it's name). But even just getting the name seems impossible. Without the name, how can I differentiate the types? Here are few things I tried:
proc test1*(T: typedesc) = # OK
echo("ok") # OK
test1(int) # OK, because it doesn't even use T!
proc test2*(T: static[typedesc]) = # OK
echo(T.name) # OK
test2(int) # COMPILE ERROR
proc test3*(T: typedesc) = # OK
echo(T.name) # COMPILE ERROR
test3(int) # OK
OH MY GOD! I just discovered the forum has a Run button, and it actually does what you expect! What kind of sorcery is that?
I also tried this, with no luck:
proc test4*(name: static[cstring]) = # OK
echo(name) # OK
proc test4*(T: static[typedesc]) = test4(T.name) # OK
test4(int) # ERROR
I think your third example should work if you import typetraits.
Actually let's test the forum feature...
import typetraits
proc test3*(T: typedesc) =
echo(T.name)
test3(int)
Yes, i saw this change yesterday. This is actually a great addition. Suggestion: Make it work in preview too. And some animation indicating the code is compiling.
On the subject, there are several issues with this snippet:
First and second proc compiled alright because generics are ignored until some code employs them (needs context to check whether it compiles or not)
import typetraits
proc test4*(name: static[cstring]) = echo(name)
proc test4*(T: typedesc) = test4(T.name)
test4(int)
@LeuGim sorry to hear that, I'll try to fix it later today.
I'm not a webdev, so I was under the impression that the Access-Control... part was to be done server-side.
As for the innerText bit, you are right, Firefox only added it in 45. I'll try using textContent instead, which should be good for IE9+.
Other common suggestions seem to be:
And maybe a button to go to play.nim-lang.org?
(Sorry for going OT, if you have more suggestions consider raising an issue in nimforum repo)
Importing typetraits solved the problem. I would have a related question.
Since I want to store the type name on the first call for that type, and since I cannot store the string itself because it will be stored on the shared heap, I assume I have to use the cstring. The manual says:
"Even though the conversion is implicit, it is not safe: The garbage collector does not consider a cstring to be a root."
So I cannot keep/store the cstring directly either. Will this do the job correctly?
proc copyCString(s: cstring, len: int): cstring =
result = cast[cstring](allocShared(len+1))
copyMem(cast[pointer](result), cast[pointer](s), len+1)
let s = "abc"
echo copyCString(s.cstring, len(s))
Hi monster,
write a proc that returns the same integer ID, when called with the same type, from any thread (ID can change on every run)
I had to do this for my entity component system. Since I needed to store the name of the types to generate their accessors, I just store the type name and look it up, returning the index.
There are two ways of doing this. Firstly at run time using typetraits to get the type name which you've already tried.
Secondly, at compiletime:
var ctTypeNames {.compileTime.} = newSeq[string]()
import macros
proc findTypeId(name: string): int {.compiletime.} =
let idx = ctTypeNames.find(name)
if idx > -1: return idx
else:
ctTypeNames.add name
return ctTypeNames.high
macro getTypeId(t: untyped): untyped =
result = newIntLitNode(findTypeId($t))
# constrain to just accept types
template typeId*(t: typedesc): int = getTypeId(t)
echo typeId(int)
echo typeId(int32)
echo typeId(string)
echo typeId(int)
type MyObj = object
echo typeId(MyObj)
If you inspect the C code from the above, you can see typeId(X) is replaced by an appropriate static integer (in this case converted to a const string for echo), so no runtime work and completely thread safe.
Note that if you try and do anything with ctTypeNames at runtime, you'll get a cgen error saying it doesn't exist.
Because of this, if you need to access the type names at runtime and want to keep compiletime evaluation of the id, you're going to have use a macro to construct a runtime accessible variable (such as a seq or array) whose elements are populated from ctTypeNames. If you want I can add the code to do that here later.
Also note that getTypeId will accept anything, including procs, should you need to give them an id too.
Hope this helps!