// Feature 1 — TYPE-position pack projection `xs.T`. The per-element protocol // type-arg `T` projects into a Pack of types, usable in type/signature // positions: a tuple type `(..xs.T)` and a closure signature // `Closure(..xs.T) -> R`. (`T` of each element comes from its // `impl Box(T) for `.) #import "modules/std.sx"; Box :: protocol(T: Type) { get :: () -> T; } IntCell :: struct { v: s64; } StrCell :: struct { s: string; } Dbl :: struct { n: s64; } impl Box(s64) for IntCell { get :: (self: *IntCell) -> s64 => self.v; } impl Box(string) for StrCell { get :: (self: *StrCell) -> string => self.s; } impl Box(s64) for Dbl { get :: (self: *Dbl) -> s64 => self.n * 2; } // Tuple type `(..xs.T)` — heterogeneous (s64, string), matched by the // value-projection `(..xs.get)`. snap :: (..xs: Box) -> void { t : (..xs.T) = (..xs.get); print("0={} 1={}\n", t.0, t.1); } // Closure signature `Closure(..xs.T) -> s64` — here `Closure(s64, s64) -> s64`. // The closure literal's params are contextually typed from the projection. fold :: (..xs: Box) -> s64 { cb : Closure(..xs.T) -> s64 = (a, b) => a + b; return cb(xs[0].get(), xs[1].get()); } main :: () -> s32 { snap(IntCell.{ v = 42 }, StrCell.{ s = "hi" }); // (s64, string) print("fold={}\n", fold(IntCell.{ v = 10 }, Dbl.{ n = 5 })); // 10 + 10 = 20 0; }