var context:TableRef[string,object]
var context:TableRef[string, any]
Compiler prevents any ,`object` as key or value!
I want Nim counterpart as Java 'Object', Is there one?
Thanks!
var context: TableRef[string, RootRef]
RootRef is a reference to RootObj, the root of Nim's object hierarchy. You can't use RootObj directly, because non-ref objects are stored in-place, so you would not have enough space there for every kind of object. RootRef is instead what Java's object is, a pointer/reference to a memory location with the actual object.but RootRef do not contains string,`int`, etc, how to take these types into account?
#let context = newTable[string, RootRef|string]() #error
let context = newTable[string, RootRef]()
context.add("key", [1,2,3])
context.add("key",@[])
context.add("key",1)
context.add("key","value")
can not passIn Java, primitive values such as int are autoboxed into instances of Integer whenever you use them in generic contexts, such as values of hashtables.
In Nim, int and ref int are distinct types. You are able to store a ref int into your context table but not int. The reason is that Nim allows many more types to be allocated on the stack, and their size can vary. There is no upper on their size to store them safely into hashtables, while pointers take a constant space.
If you want to do autoboxing, you can write your overload of the add function, say for int, that allocates a new ref int, stores the value there and then puts the ref into the table.
I think the point here is that Nim should not be used as if it's Java, because it's not. Even Java itself moved from Maps/Lists with Objects to generic types in 1.5 (even though they are still awful because of type erasure).
In Nim, if you want a variable to be able to hold values of several different types, you can use object variants. The case where you actually want to put any type into a variable is exotic and most of the time not the ideal solution for the problem at hand.
Using object variants is really terrible for me:
type
Kind* = enum # the different node types
nkInt, # an integer value
nkFloat, # a float value
nkString, # a string value
nkSeq,
nkArray,
nkRef,
nkTuple
ContextObj* = ref ContextObjObj
ContextObjObj = object
case kind: Kind # the ``kind`` field is the discriminator
of nkInt: intVal*: int
of nkFloat: floatVal*: float
of nkString: strVal*: string
of nkSeq, nkArray:
seqVal*: seq[string] #how to define more
of nkRef:
refVal*: RootRef
of nkTuple:
tupleVal*: tuple[t1:string,t2:string] #how to define more?
A lot and unpredictable.
tuple[int,string], tuple[int,string,string],tuple[int,string, Time], etc
Complete list is nearly impossible.
You can also use inheritance instead of case objects:
type
SeqWrapper = ref object of RootObj
s: seq[RootRef]
TimeWrapper = ref object of RootObj
t: Time
IntWrapper = ref object of RootObj
i: int
I write some more clear code , but fail to compile :
import tables
type
ObjRef* = ref Obj
Obj* = SomeNumber | enum | string | seq[SomeNumber] | seq[enum] | seq[string]
type
Session* = ref SessionObj
SessionObj = object
context*: TableRef[string,ObjRef]
when isMainModule:
var s = new(Session) #Error: cannot evaluate at compile time: T
s.context = newTable[string,ObjRef]()
s.context.add("key",123)
g:\dev\nim\webapp\pkg\ctxobj.nim(19, 15) template/generic instantiation from here
e:\yexy6\nim-0.13.0\lib\system.nim(190, 9) Error: cannot evaluate at compile time: T