Are seq always allocated on the heap and garbage collected?
Is it possible that when the compiler is able to determine the length, or prove that it is short enough anyway, sequences could be represented as stack-allocated C arrays or variable length arrays?
when the compiler is able to determine the length
But the length for seqs is changeable at runtime. If you know max length you need in advance you just use static arrays, like array[0..9, int].
Is it possible that when the compiler is able to determine the length, or prove that it is short enough anyway, sequences could be represented as stack-allocated C arrays or variable length arrays?
Yes and once the compiler gets the optimizer it deserves which includes escape analysis, it's simple to do. There is no need for yet another slightly different builtin type to get that feature.
That would be wonderful! :-)
By the way, the following naive solution:
type VLA*[N: static[int], A] = object
content: array[0 .. N - 1, A]
length: int
proc newVLA*[N: static[int], A]: VLA[N, A] =
VLA[N, A](content: array[0 .. N - 1, A], length: N)
proc low*[N: static[int], A](a: VLA[N, A]): int = 0
proc high*[N: static[int], A](a: VLA[N, A]): int = a.length
proc len*[N: static[int], A](a: VLA[N, A]): int = a.length
iterator items*[N: static[int], A](a: VLA[N, A]) =
for i in 0 .. < a.length:
yield a.content[i]
proc `[]`*[N: static[int], A](a: var VLA[N, A], key: int): A =
if key < 0 or key > N: raise RangeError
a.content[key]
proc `[]=`*[N: static[int], A](a: var VLA[N, A], key: int, val: int) =
if key < 0 or key > N: raise RangeError
a.content[key] = val
if key >= a.length: a.length = key + 1
fails with Error: type expected when I do
let v = newVLA[15, int]()
or even
let v: VLA[15, int] = newVLA[15, int]()
var v: VLA[15, int]
And you should add new before RangeError.
Also there are issues reported, e.g. https://github.com/Araq/Nim/issues/1017.
And you cannot use the same with let, because then you need to provide value, and it's unchangeable, so there's no point (you can then use just an array, if it's not changed).
Could we have a seq type with a fill pointer?
It would allow you to have a newStringOfCap() equivalent for seq.
(make-array 1000 :fill-pointer 0)
proc newSeqF(size, fillPointer = 0)