Skip to content

Commit 3207f22

Browse files
committed
[spec/template.dd] Improve TemplateSequenceParameter docs
Any argument passed to an alias parameter can be passed to a sequence parameter. Show AliasSeq definition. Link to `articles/ctarguments`. `typeof` can be used on a *ValueSeq* to obtain a *TypeSeq*. Mention a sequence is automatically expanded when referenced in a declaration or expression. Split print/write example into 2 - one with ValueSeq arguments, one with TypeSeq arguments. A *TypeSeq* can similarly be used to declare lvalue variables. Add *Sequence Operations* subheading & add example. Explain how to construct a sequence from an existing one. Mention AliasAssign for iterative construction. Mention foreach on a sequence. type.dd: `typeof` can be used on a *ValueSeq* to obtain a *TypeSeq*.
1 parent 3eaea19 commit 3207f22

File tree

2 files changed

+92
-24
lines changed

2 files changed

+92
-24
lines changed

spec/template.dd

Lines changed: 88 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -818,60 +818,124 @@ $(GNAME TemplateSequenceParameter):
818818

819819
$(P If the last template parameter in the $(I TemplateParameterList)
820820
is declared as a $(I TemplateSequenceParameter),
821-
it is a match with any trailing template arguments.
822-
Such a sequence of arguments can be defined using the template
823-
$(REF AliasSeq, std,meta) and will thus henceforth
821+
it is a match with zero or more trailing template arguments.
822+
Any argument that can be passed to a $(GLINK TemplateAliasParameter)
823+
can be passed to a sequence parameter.
824+
)
825+
$(P Such a sequence of arguments can itself be aliased for use outside
826+
a template. The $(REF AliasSeq, std,meta) template simply
827+
aliases its sequence parameter:)
828+
---
829+
alias AliasSeq(Args...) = Args;
830+
---
831+
$(P A *TemplateSequenceParameter* will thus henceforth
824832
be referred to by that name for clarity.
825-
An $(I AliasSeq) is not itself a type, value, or symbol.
826-
It is a compile-time sequence of any mix of types, values or symbols.
833+
An $(I AliasSeq) is not itself a type, value, or symbol. It is a
834+
$(DDLINK articles/ctarguments, Compile-time Sequences, compile-time sequence)
835+
of any mix of types, values or symbols, or none.
827836
)
828-
829-
$(P An $(I AliasSeq) whose elements consist entirely of types is
830-
called a type sequence or $(I TypeSeq).
831-
An $(I AliasSeq) whose elements consist entirely of values is
832-
called a value sequence or $(I ValueSeq).
837+
$(UL
838+
$(LI An $(I AliasSeq) whose elements consist entirely of types is
839+
called a type sequence or $(I TypeSeq).)
840+
$(LI An $(I AliasSeq) whose elements consist entirely of values is
841+
called a value sequence or $(I ValueSeq).)
842+
$(LI `typeof` can be used on a *ValueSeq* to obtain a *TypeSeq*.)
833843
)
834844

835-
$(P An $(I AliasSeq) can be used as an argument list to instantiate
836-
another template, or as the list of parameters for a function.)
845+
$(P The elements of an $(I AliasSeq) are automatically expanded
846+
when it is referenced in a declaration or expression.
847+
An $(I AliasSeq) can be used as arguments to instantiate a
848+
template. A *ValueSeq* can be used as arguments to call a
849+
function:)
837850

838851
$(SPEC_RUNNABLE_EXAMPLE_RUN
839852
---
840-
import std.stdio;
853+
import std.stdio : writeln;
841854

842-
template print(args...)
855+
template print(args...) // args must be a ValueSeq
843856
{
844857
void f()
845858
{
846-
writeln("args are ", args); // args is a ValueSeq
859+
writeln("args are ", args);
847860
}
848861
}
849862

850-
template write(Args...) // Args is a TypeSeq
863+
void main()
864+
{
865+
print!(1,'a',6.8).f(); // prints: args are 1a6.8
866+
}
867+
---
868+
)
869+
870+
$(P A *TypeSeq* can be used to declare parameters for a function:)
871+
872+
$(SPEC_RUNNABLE_EXAMPLE_RUN
873+
---
874+
import std.stdio : writeln;
875+
876+
template print(Types...) // Types must be a TypeSeq
851877
{
852-
void f(Args args) // args is a ValueSeq
878+
void f(Types args) // args is a ValueSeq
853879
{
854880
writeln("args are ", args);
855881
}
856882
}
857883

858884
void main()
859885
{
860-
print!(1,'a',6.8).f(); // prints: args are 1a6.8
861-
write!(int, char, double).f(1, 'a', 6.8); // prints: args are 1a6.8
886+
print!(int, char, double).f(1, 'a', 6.8); // prints: args are 1a6.8
862887
}
863888
---
864889
)
865890

866-
$(P The number of elements in an $(I AliasSeq) can be retrieved with
867-
the $(D .length) property. The $(I n)th element can be retrieved
868-
by indexing the $(I AliasSeq) with [$(I n)],
869-
and sub-sequences are denoted by the slicing syntax.
891+
$(P A *TypeSeq* can similarly be used to
892+
$(DDSUBLINK articles/ctarguments, type-seq-instantiation, declare variables).
893+
Parameters or variables declared with a *TypeSeq* are called an
894+
*lvalue sequence*.)
895+
896+
$(H4 $(LNAME2 seq-ops, Sequence Operations))
897+
898+
$(UL
899+
$(LI The number of elements in an $(I AliasSeq) can be retrieved with
900+
the $(D .length) property.)
901+
$(LI The $(I n)th element can be retrieved by
902+
$(DDSUBLINK spec/expression, index_expressions, indexing) an
903+
$(I AliasSeq) with `Seq[n]`. Indexes must be known at compile-time.
904+
The result is an lvalue when the element is a variable.)
905+
$(LI Sub-sequences can be obtained using
906+
$(DDSUBLINK spec/expression, slice_expressions, slicing) syntax.)
907+
)
908+
909+
$(SPEC_RUNNABLE_EXAMPLE_RUN
910+
---
911+
import std.meta : AliasSeq;
912+
913+
int v = 4;
914+
alias nums = AliasSeq!(1, 2, 3, v);
915+
static assert(nums.length == 4);
916+
static assert(nums[1] == 2);
917+
918+
// nums[3] is bound to v, an lvalue
919+
nums[3]++;
920+
assert(v == 5);
921+
922+
// slice first 3 elements
923+
alias trio = nums[0 .. $-1];
924+
// expand into an array literal
925+
static assert([trio] == [1, 2, 3]);
926+
---
870927
)
871928

872-
$(P $(I AliasSeq)-s are static compile-time entities, there is no way
929+
$(P $(I AliasSeq)s are static compile-time entities, there is no way
873930
to dynamically change, add, or remove elements either at compile-time or run-time.
931+
Instead, either:)
932+
$(UL
933+
$(LI Construct a new sequence using the original sequence (or a slice of it) and additional elements before or after it.)
934+
$(LI Use $(DDSUBLINK spec/declaration, AliasAssign, Alias Assignment)
935+
to build a new sequence iteratively.)
874936
)
937+
$(P Sequences can 'unroll' code for each element using a
938+
$(DDSUBLINK spec/statement, foreach_over_tuples, `foreach` statement).)
875939

876940
$(H4 $(LNAME2 typeseq_deduction, Type Sequence Deduction))
877941

spec/type.dd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,10 @@ $(GNAME Typeof):
468468
}
469469
--------------------
470470

471+
$(P If *Expression* is a
472+
$(DDSUBLINK spec/template, variadic-templates, $(I ValueSeq))
473+
it will produce a *TypeSeq* containing the types of each element.)
474+
471475
$(P Special cases: )
472476
$(OL
473477
$(LI $(D typeof(this)) will generate the type of what $(D this)

0 commit comments

Comments
 (0)