I am a novice in nim and don't know much about the type system. I went through the documentation and found this out
All expressions have a type which is known at compile time. Nim is statically typed.
Is there any way I can create typed variables at runtime? Here is what I am trying to achieve. I get a JSON from the client which gives me the type and value, both as strings as shown below.
"args":[
{
"value":"1",
"type":"int"
}
]
I would like to create a variable of the type specified by the "type" field in the JSON and convert the value specified by the "value" field in the JSON to the type specified in the JSON. I was thinking of a function which converts this JSON to a variable and returns it to me as shown below.
proc getArg(typeName:string, strValue:string):XXXXX=
case typeName:
of "string":
result = strValue
of "int":
result = parseInt(strValue)
As you can see the return type of the function is set to XXXX as I didn't know what it actually should be. I read about macros and templates and found out that both of them operate at compile time and not run time. What is the best way to achieve this? Or is this not possible?
Static types, by definition, have to be known at compile time, so there is not much you can do for that.
What you can do is mimic what dynamic languages do and write a wrapper type using object variants. You can see an example for json here
Well you cannot create types at runtime.
type
VariantKind = enum
vkString
vkInt
VariantType = object
case kind: VariantKind
of vkString:
strValue: string
of vkInt:
intValue: int
proc getArg(typeName:string, strValue:string): VariantType =
case typeName:
of "string":
result.kind = vkString
result.strValue = strValue
of "int":
result.kind = vkInt
result.intValue = parseInt(strValue)
else:
# do some error handling
discard
Krux's solution is the most efficient. You can also use inheritance:
import strutils
type
BaseType = ref object of RootObj
StringType = ref object of BaseType
value: string
IntType = ref object of BaseType
value: int
method toString(bt: BaseType): string {.base.} = ""
method toString(st: StringType): string = st.value
method toString(it: IntType): string = $it.value
proc getArg(typeName:string, strValue:string):BaseType=
case typeName:
of "string":
result = StringType(value: strValue)
of "int":
result = IntType(value: parseInt(strValue))
let bt = getArg("int", "777")
echo "ToString: ", toString(bt)
if bt of StringType:
echo("Casting: ", StringType(bt).value)
elif bt of IntType:
echo("Casting: ", IntType(bt).value)
run it