Lis* = ref seq[MalType] not nil
but when I try to initialize it like this
x: Lis = @[] #or
x: Lis[] = @[]
i get a errorHere you go:
# init
var x = new seq[int]
# use
x[].add 5
echo x[]
building a lisp. the code was as follows.
MalType* = object
case mk*: Mk
of mklist: lis*: seq[MalType]
of mkint: intval: int
of mkstring: strval: string
of mkfloat: floatval: float
of mkbool: boolval: bool
because of the recursive nature I thought ref type would be more efficient hereI chose
type
MalType* = enum
kSym,kNum,kString,kList,kVector,kTable,kKeyword,kNil,kTrue,kFalse,kProc
MalNode* = object
case kind*:MalType
of kList,kVector: lst*:seq[MalNode]
of kTable: tab*:Table[MalNode,MalNode]
of kSym,kKeyword,kString: str*:string
of kNum: num*:int
of kNil,kTrue,kFalse : nil
of kProc: f*:proc(x:int,y:int):int
sizeof(MalNode) = 24
seq and string are both on the heap
Ah, as I expected. Not entirely sure why you believe a ref type would be more efficient. Remember with ref types the computer has to go fetch data from a completely different region of memory which can lead to poor cache utilization. What's more is that seq is already using a reference internally. Essentially a seq in Nim is something like:
type seq[T] = object
capacity: int
len: int
data: ptr UncheckedArray[T]
As you can see the underlying data is already stored through the indirection of a pointer/ref. This means that the only thing you're moving to the heap with your ref seq is the three int-sized fields that control the sequence. In some cases when you have recursive types you must use a reference, but that is simply because storing a full object within the object itself would lead to the object being infinitely big. However the seq will always be the same size in that field (two ints and a pointer) so having a reference like that is fine.
There is also newSeqWith from sequtils: https://nim-lang.org/docs/sequtils.html#newSeqWith.t%2Cint%2Cuntyped
Works great for me.