Skip to content

Commit

Permalink
Update variadic templates section
Browse files Browse the repository at this point in the history
Use clearer names for variadic auto ref arguments.
Move tuple length and slicing details before example using length.
Update curry example -> partial and simplify by returning a closure.
  • Loading branch information
ntrel committed Sep 11, 2014
1 parent 2998ebd commit f1b72f9
Showing 1 changed file with 38 additions and 49 deletions.
87 changes: 38 additions & 49 deletions template.dd
Expand Up @@ -729,20 +729,20 @@ $(GNAME TemplateTupleParameter):
another template, or as the list of parameters for a function.

---
template Print(A ...)
template Print(args...)
{
void print()
{
writefln("args are ", A);
writeln("args are ", args); // args is an ExpressionTuple
}
}

template Write(A ...)
template Write(Args...)
{
void write(A a) // A is a TypeTuple
// a is an ExpressionTuple
void write(Args args) // Args is a TypeTuple
// args is an ExpressionTuple
{
writefln("args are ", a);
writeln("args are ", args);
}
}

Expand All @@ -754,24 +754,35 @@ $(GNAME TemplateTupleParameter):
---
)

$(P The number of elements in a $(I Tuple) can be retrieved with
the $(D .length) property. The $(I n)th element can be retrieved
by indexing the $(I Tuple) with [$(I n)],
and sub tuples can be created
with the slicing syntax.
)

$(P $(I Tuple)s are static compile time entities, there is no way
to dynamically change, add, or remove elements.
)

$(P Template tuples can be deduced from the types of
the trailing parameters
of an implicitly instantiated function template:

---
template Foo(T, R...)
template print(T, Args...)
{
void Foo(T t, R r)
void print(T first, Args args)
{
writeln(t);
static if (r.length) // if more arguments
Foo(r); // do the rest of the arguments
writeln(first);
static if (args.length) // if more arguments
print(args); // recurse for remaining arguments
}
}

void main()
{
Foo(1, 'a', 6.8);
print(1, 'a', 6.8);
}
---
)
Expand All @@ -785,33 +796,21 @@ a
)
)

$(P The tuple can also be deduced from the type of a delegate
$(P Template tuples can also be deduced from the type of a delegate
or function parameter list passed as a function argument:

----
import std.stdio;

/* R is return type
* A is first argument type
* U is TypeTuple of rest of argument types
/* Partially applies a delegate by tying its first argument to a particular value.
* R = return type
* T = first argument type
* Args = TypeTuple of remaining argument types
*/
R delegate(U) Curry(R, A, U...)(R delegate(A, U) dg, A arg)
R delegate(Args) partial(R, T, Args...)(R delegate(T, Args) dg, T first)
{
struct Foo
{
typeof(dg) dg_m;
typeof(arg) arg_m;

R bar(U u)
{
return dg_m(arg_m, u);
}
}

Foo* f = new Foo;
f.dg_m = dg;
f.arg_m = arg;
return &f.bar;
// return a closure
return (Args args) => dg(first, args);
}

void main()
Expand All @@ -821,21 +820,11 @@ a
return x + y + z;
}

auto plus_two = Curry(&plus, 2);
auto plus_two = partial(&plus, 2);
writefln("%d", plus_two(6, 8)); // prints 16
}
----
)

$(P The number of elements in a $(I Tuple) can be retrieved with
the $(D .length) property. The $(I n)th element can be retrieved
by indexing the $(I Tuple) with [$(I n)],
and sub tuples can be created
with the slicing syntax.
)

$(P $(I Tuple)s are static compile time entities, there is no way
to dynamically change, add, or remove elements.
See also: $(FULL_XREF functional, partial)
)

$(H3 Specialization)
Expand All @@ -848,7 +837,7 @@ $(H3 Specialization)
template Foo(T) { pragma(msg, "1"); } // #1
template Foo(int n) { pragma(msg, "2"); } // #2
template Foo(alias sym) { pragma(msg, "3"); } // #3
template Foo(A ...) { pragma(msg, "4"); } // #4
template Foo(Args...) { pragma(msg, "4"); } // #4

import std.stdio;

Expand Down Expand Up @@ -1110,16 +1099,16 @@ $(H3 $(LNAME2 auto-ref-parameters, Function Templates with Auto Ref Parameters))
a value parameter:

---
int foo(T...)(auto ref T x)
int foo(Args...)(auto ref Args args)
{
int result;

foreach (i, v; x)
foreach (i, v; args)
{
if (v == 10)
assert(__traits(isRef, x[i]));
assert(__traits(isRef, args[i]));
else
assert(!__traits(isRef, x[i]));
assert(!__traits(isRef, args[i]));
result += v;
}
return result;
Expand Down

0 comments on commit f1b72f9

Please sign in to comment.