# A Tour of Morfa

## Value template parameters

In Morfa it is also possible to parametrize declaration with a value. For example, you may declare a generic type `Point<N>` for points in the `N`-dimensional Euclidean space:

``````import morfa.util.Slice;
import morfa.math.base: sqrt;

public template <N: int>
class Point
{
private var coordinates: float[N];

public func new(coords: float[N])
{
for (i in 0 .. N)
coordinates[i] = coords[i];
}

public template <K: int> if (K > 0 and K <= N)
property get(): float
{
return coordinates[K-1];
}
}

unittest
{
var p = new Point<3>([1.0, 2.0, 3.0]);
assert (p.get<1> == 1.0);
assert (p.get<2> == 2.0);
assert (p.get<3> == 3.0);
// This would produce a compilation error:
// var t = p.get<4>;
}
``````

A generic function `distance` that computes an Euclidean distance between two `N`-dimensional points is also parametrized by an integer value:

``````public template <N: int>
func distance(p: Point<N>, q: Point<N>): float
{
var distance = 0.0;
for (i in 0 .. N)
{
var delta = (p.coordinates[i] - q.coordinates[i]);
distance += delta * delta;
}
return sqrt(distance);
}
``````

Template argument deduction works for value parameters as well: you do not have to provide explicit template arguments to `distance` below, since they can be deduced from function arguments:

``````unittest
{
alias Point3 = Point<3>;
var p = new Point3([0.0, 1.0, 0.0]);
var q = new Point3([1.0, 0.0, 1.0]);
var d = distance(p, q);
assert (d == sqrt(3.0));
}
``````

A template declaration may contain both type and value parameters. For example, we may declare a type of lists of at most `N` elements of type `T` as follows:

``````public template <T, N: int> if (N > 0)
class BoundedList
{
public var elem: T;
public var next: BoundedList<T, N-1>;

public func new(head: T, tail: BoundedList<T, N-1>)
{
next = tail;
}
}
``````

A base case for `N = 0` may be defined using template parameter specification and the keyword `is` (an alternative would be to use a constraint with `N == 0`):

``````public template <T, N: int is 0>
abstract class BoundedList {}

unittest
{
var ints0: BoundedList<int,0> = null;
var ints1 = new BoundedList<int,1>(1, null);
var ints2 = new BoundedList<int,2>(1, new BoundedList<int,1>(2, null));
}
``````

As was the case with generic lists we defined in section on class and struct templates, it is convenient to introduce a template function for constructing bounded lists:

``````public template <T, N: int> if (N >= 0)
func cons(head: T, tail: BoundedList<T, N>): BoundedList<T,N + 1>
{
}
``````

You may also define a const template for creating empty lists:

``````public template <T, N: int>
const nil: BoundedList<T,N> = null;
``````

Note that `null` is a valid value of a type `BoundedList<T, N>` for any `N` and `T`, not only for `N = 0`.

``````unittest
{
var list0: BoundedList<int,0> = null;
var list1: BoundedList<int,1> = cons(1, list0);
var list2: BoundedList<int,2> = cons(2, list1);
var list3: BoundedList<int,3> = cons(3, list2);

var list31: BoundedList<int,3> = nil<int,3>;
var list32: BoundedList<int,3> = cons(1, nil<int,2>);
}
``````