Here is an example of template metaprogramming in ATS3:
(* ****** ****** *)
abstype Z
abstype S(type)
(* ****** ****** *)
#extern
fun
<a:t0>
<N:t0>
<n:i0>
dotprodN
( xs: array(a, n)
, ys: array(a, n)): a
(* ****** ****** *)
impltmp
{a:t0}
dotprodN
<a><Z><0>(_, _) = g_0<a>()
(* ****** ****** *)
impltmp
{a:t0}
{N:t0}
{n1:i0}
dotprodN
<a><S(N)><n1>
{n1 > 0}(xs, ys) =
head(xs)*head(ys)+dotprodN<a><N><n1-1>(tail(xs),tail(ys))
(* ****** ****** *)
The above ATS code roughly corresponds to the following C++ code:
template<typename T, std::size_t N>
struct DotProductT {
static inline T result(T* a, T* b) {
return *a * *b + DotProduct<T, N-1>::result(a+1,b+1);
}
};
*// partial specialization as end criteria*
template<typename T>
struct DotProductT<T, 0> {
static inline T result(T*, T*) {
return T{};
}
};
On Sunday, July 5, 2020 at 6:53:44 PM UTC-4, gmhwxi wrote:
>
>
> When I see a programming feature, I tend to ask myself immediately how
> such a feature
> can be implemented. Not trying to get the fine details. Just the big
> picture.
>
> The template system in C++ is first and foremost a macro system. Of
> course, in order to
> better understand C++, we need to start with C.
>
> In programming language implementation, we face the issue of binding of
> names early on.
> Basically, if a function foo is used in some code, we need to figure out
> where the 'foo' is declared.
>
> For instance, static binding in ATS3 is handled in the module trans12 (for
> translating from level-1
> o level-2).
>
> C originates from assembly, which explains very well the way in which
> binding is handled in C.
> Every function in C is given a unique global name. If there are two
> functions of the same name,
> a link-time error is to be reported (by the command, say, ld). By the way,
> if I ever want to make sure
> that a chosen name is globally unique, I often just map the name to a
> dummy C function (assuming
> I am compiling to C); a link-time error is to occur if the name turns out
> to be not unique.
>
> The C++ template system handles binding like C but with a twist, that is,
> overloading resolution. In short,
> if there are two or more declarations for a name, say. foo, then there
> needs to be a way to determine
> which of these declarations should be selected. C++ makes heavy use of the
> types of the arguments of
> foo when determine the selection. Once a template/macro declaration is
> selection, it is used to perform
> macro expansion; and the expanded code goes through type-checking.
>
> ATS does binding based on the model of lambda-calculus, which is the gold
> standard for static binding.
> Actually, Alonzo Church invented lambda-calculus for studying binding and
> substitution. After each template
> function is declared, it can be implemented in a legal scope as many times
> as is needed. Note that a legal
> scope refers to one where the declared template function is accessible.
> Let me use an example to clarify a bit.
> The following template function g_equal is for testing whether two given
> values are equal:
>
> #extern
> fun
> <a:type>
> g_equal(x: a, y: a): bool
>
> impltmp
> g_equal<int>(x, y) = (x = y) // integer equality
>
> impltmp
> <a:type>
> g_equal<list(a)>(xs, ys) = .... // equality on lists
>
> The first implementation of g_equal is given the type:
>
> (int, int) -> bool
>
> The second implementation of g_equal is given the type:
>
> {a:type} (list(a), list(a)) -> bool
>
> Note that both implementations have types that are special
> instances of the general type for g_equal:
>
> {a:type} (a, a) -> bool
>
> Say g_equal is used in some code. ATS uses the type of this instance of
> g_equal
> to select (based the static scoping principle) the "closest"
> implementation of g_equal
> that has a matching type. There is no macro expansion involved. At least
> not in the
> traditional sense.
>
> Where is the need for traits in ATS3?
>
> The search used for template resolution ATS3 is like finding a matching
> ancestor in a tree
> (of implementations of a template functions).
>
> Say that an ancestor is found. Is it the right one? If some form of
> backtracking is allowed,
> then we can determine whether it is the right one later. But if no
> backtracking is allowed,
> then one often applies a quick test to tell if the found ancestor should
> be returned or skipped.
> And traits can be used to construct this quick test.
>
> In summary, I envision introducing traits in ATS3 to affect the way in
> which template resolution
> is performed.
>
> Cheers!
>
> --Hongwei
>
>
>
>
>
>
--
You received this message because you are subscribed to the Google Groups
"ats-lang-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/ats-lang-users/0d199a8d-e203-457a-b77b-10223c634dd8o%40googlegroups.com.