-
Notifications
You must be signed in to change notification settings - Fork 52
attached type parameters #121
Description
generic containers work, but i still hate them somehow. i thought not knowing the interior type is fine because thats what golang does too, but then golang has reflection so you can get the interior at runtime.
this is unfixably unsafe
new+10 v = map::make();
u8 val =12;
v.insert("hello", &val);
u64 * bad = v.get("hello");
well , not unfixable, vec could just store the typeid, but then it's checked at runtime, which is terrible.
new+10 v = map::make();
u8 val =12;
v.insert("hello", &val);
u64 meh;
v.get("hello", &meh);
typestate would help
struct Vec+t {
}
theory item (Vec self) typeid;
pub fn get(Vec+t mut * self) void *
model typeid(return) == item(self)
{
}
pub fn main() {
new+10 v = vec::make();
static_attest(val::item(&v) == typeid(u8));
u8 val =12;
v.push(&val);
u64 * bad = v.get("hello"); // error: implicit cast of void pointer to different type
}this elegantly fits into the powerful smt theories, but it doesn't answer the question of how to decode a struct from json
struct Foo {
Vec::vec+100 something; // dunno which type is in this
}
Other languages do "templates" so they just create a new type for each possible parameter. That's horribly inefficient, as each instance also has to have all of its functions duplicated. It also doesnt map to C.
Instead i'm proposing to just attach the interiour typestate to the external typestate permanently somehow, creating a new virtual type. That's essentially just what tail already is, a permanent type state.
One possible syntax is just reusing the familiar template angled brackets. however, the tail marker has to go somewhere
struct Vec<typeid Item>
struct Vec+t<typeid Item>
struct Vec<typeid Item>+t
struct Vec<typeid Item, +t>
pub fn get (Vec<Item, +t> mut * self) void<Item> *
{
}
pub fn main() {
new<u8,+10> v = vec::make();
u8 val =12;
v.push(&val);
u64 * bad = v.get("hello"); // error: implicit cast of void<u8> pointer to wrong type
}
benefit is, it looks immediately familiar. disadvantage is that the familiarity is a trap. This is not a template, and you cannot actually use it in place of a typename.
struct VecWrapper<typeid Item> {
Vec<Item> inner; // ok
Item example; // nope, Item is a typeid, not a type
}i personally also think angled brackets are a terrible syntactical choice because they're also math operators, but that's what the world agreed on, so be it. We could of course use square brackets or whatever.
struct Vec[typeid Item, +t]
another way to deal with this is creating a way to make integrity theories permanent somehow.
struct Vec+t {}
theory item (Vec self) typeid;
type ByteVec = Vec+t
where item(self) = typeid(u8)
;
struct A+
{
ByteVec+ buffer;
}
it's difficult to decide between these two options. Allowing a type alias that includes a permanent smt theory is very powerful, but also difficult to understand. The type "templates" are immediately obvious.