Open StijnWoestenborghs opened 7 months ago
Seems like compile time evaluation is quite volatile right now.
I tried something very simple and it still didn't work:
from collections import Optional
struct Dict[T: CollectionElement](Sized):
var keys: DynamicVector[StringLiteral]
var values: DynamicVector[T]
fn __init__(inout self, *values: Tuple[StringLiteral, Int]):
self.keys = DynamicVector[StringLiteral](len(values))
self.values = DynamicVector[T](len(values))
for i in range(len(values)):
self.keys.push_back(values[i].get[0, StringLiteral]())
self.values.push_back(values[i].get[1, Int]())
fn __init__(inout self, *values: Tuple[StringLiteral, StringLiteral]):
self.keys = DynamicVector[StringLiteral](len(values))
self.values = DynamicVector[T](len(values))
for i in range(len(values)):
self.keys.push_back(values[i].get[0, StringLiteral]())
self.values.push_back(values[i].get[1, StringLiteral]())
fn __getitem__(self, key: String) raises -> T:
for i in range(len(self.keys)):
if String(self.keys[i]) == key:
return self.values[i]
raise String("No value for key ") + key
fn __len__(self) -> Int:
return len(self.keys)
fn main() raises:
let ds = Dict[StringLiteral](("a", "this is it"))
# alias ds = Dict[StringLiteral](("a", "this is it"))
print("len", len(ds))
print("a:", ds["a"])
let di = Dict[Int](("a", 1), ("b", 2))
# alias di = Dict[Int](("a", 1), ("b", 2))
print("len", len(di))
print("a:", di["a"])
So I would postpone this issue. Lets keep it around though.
Yeah I have been doing this more and more lately and you have to be very careful to get this to work. Basically you need to make sure that all (or most?) the datatypes you are using are register passable. Having that as best practice is generally working for me. In this case your Tuple (StaticTuple might work) and/or StringLiteral is not. This example is working for me:
struct Dict[T: CollectionElement](Sized):
var keys: DynamicVector[String]
var values: DynamicVector[T]
fn __init__(inout self):
self.keys = DynamicVector[String]()
self.values = DynamicVector[T]()
fn put(inout self, key: String, value: T):
self.keys.push_back(key)
self.values.push_back(value)
fn get(self, key: String, default: T) -> T:
for i in range(len(self.keys)):
if self.keys[i] == key:
return self.values[i]
return default
fn __len__(self) -> Int:
return len(self.keys)
fn __moveinit__(inout self, owned other: Self):
self.keys = other.keys^
self.values = other.values^
fn create_dict() -> Dict[String]:
var d = Dict[String]()
d.put("a", "this is it")
return d^
fn create_dict2() -> Dict[Int]:
var d = Dict[Int]()
d.put("b", 0)
return d^
fn main():
alias ds = create_dict()
print("len", len(ds))
print("a:", ds.get("a", "default"))
alias di = create_dict2()
print("len", len(di))
print("b:", di.get("b", -1))
UPDATE: Only the Int version seems to be working consistently. You have to be very careful with Strings. Perhaps storing them as bytes internally is a better idea.
Do you think you could support compile time metaprogramming? An example of how I would try to use it:
Note that the std Dict also doesn't support this yet. You are able to initialise one there but that is it. Not sure if this is aligned with the goals of your project. So feel free to close the issue if you want.