Generics
Generic modules are parameterized modules that allow functionality for arbitrary types.
For generic modules, the generic parameters follows the module name:
// TypeA, TypeB, TypeC are generic parameters.module vector(<TypeA, TypeB, TypeC>);
It is also possible to parameterize by an int
or bool
constant, for example:
// module custom_type<Type, VALUE>module custom_type<float, 3>;
Code inside a generic module may use the generic parameters as if they were well-defined symbols:
module foo_test(<Type1, Type2>);
struct Foo{ Type1 a;}
fn Type2 test(Type2 b, Foo *foo){ return foo.a + b;}
Including a generic module works as usual:
import foo_test;
def FooFloat = Foo(<float, double>);def test_float = foo_test::test(<float, double>);
...
FooFloat f;Foo(<int, double>) g;
...
test_float(1.0, &f);foo_test::test(<int, double>)(1.0, &g);
Just like for macros, optional constraints may be added to improve compile errors:
<* @require $assignable(1, TypeB) && $assignable(1, TypeC) @require $assignable((TypeB)1, TypeA) && $assignable((TypeC)1, TypeA)*>module vector(<TypeA, TypeB, TypeC>);
/* .. code * ../
def testFunction = vector::testFunc(<Bar, float, int>);
// This would give the error// --> Parameter(s) failed validation:// @require "$assignable((TypeB)1, TypeA) && $assignable((TypeC)1, TypeA)" violated.