Index: doc/proposals/tuples.md
===================================================================
--- doc/proposals/tuples.md	(revision b0fcd0e9c5cb8cfb0efe57e6fb351703839a2a65)
+++ doc/proposals/tuples.md	(revision 16ba4897edb8e47f2990f485549b0053dee60bae)
@@ -2,97 +2,130 @@
 ======
 
-This proposal is to update tuples, as they were created by Rob in his thesis,
-to address problems that have appeared in their use since then. This proposal
-is an attempt to address some of those problems. Adding new functionality,
-updating existing features and removing some problematic features.
-
-The core of change is breaking the current restructurable tuples into
-unstructured tuples and structured tuples. Unstructured tuples handle most
-of the existing uses, with structured tuples filling in a few missing
-use cases.
+Tuples were introduced by Dave Till in K-W C, added to CFA by Rodolfo Esteves,
+and extended by Robert Schluntz. This proposal discusses updates for CFA tuples
+to address problems that have appeared in their usage over the past 6 years.
+The proposal attempts to address problems by adding new functionality, updating
+existing features, and removing some problematic ones.
+
+The core change is breaking the current restructurable tuples into unstructured
+and structured tuples. Unstructured tuples handle most of the existing uses,
+with structured tuples filling in a few missing use cases.
 
 Current State of Tuples
 -----------------------
-An overview of the current design, as the starting place for the proposal.
+An overview of the current tuples design is the starting place for the proposal.
 
 ### Tuple Syntax
 
-An overview of the syntax for the main three components of tuples, the types
-of tuples, the tuple expressions/values (constructing tuples) and tuple index
-expressions (deconstructing tuples).
-
-Current syntax for tuple types:
+Currently, tuples have three main components: tuple types, tuple
+expressions/values (constructing tuples), and tuple index expressions
+(deconstructing tuples).
+
+Current syntax for tuple types.
+
 -   Nullary: [void] or []
 -   Unary: [TYPE]
--   Binary: [TYPE, TYPE]
--   The pattern continues for three or more elements.
+-   Nary: [TYPE, TYPE, ...]
+
+Tuple types can appear in a function return and parameter declaration, or a
+tuple variable declaration. Note, the Nullary tuple is only meaningful in the
+return context,
+
+	void f(...);   // equivalent
+	[void] f(...);
+	[] f(...);
+
+as C does not support a void declaration.
+
+	int f( void x );    // disallowed
+	int f( [void] x );
+	int f( [] x );
 
 Current syntax for tuple expressions:
--   Nullary: None. (Same as `void`, use return without an expression.)
--   Unary: {EXPR} (This might be an error, but I can't make [EXPR] work.)
--   Binary: [EXPR, EXPR]
--   The pattern from binary continues for three or more elements.
-
-Current syntax for tuple index expressions, is much simpler. It uses the
-member index expression syntax, except the member name is replaced with the
-element index, which is an integer literal, showing the index of the element
-to get.
-
-Here is a brief example showing all three parts.
+
+-   Nullary: (Same as `void`, use return without an expression.)
+
+	[] f( ) { return; }
+	[] f( ) { return [] ; }
+
+-   Unary:
+
+	[int] f( ) { return 3; }
+	[int] f( ) { return [3]; }
+
+-   Nary: [EXPR, EXPR]
+
+	[int,int] f( ) { return [3,4]; }
+
+Currently, there is a parsing problem for nullary and unary tuple expression,
+which is being looked at. Hence, only these two forms work.
+
+	[] f( ) { return; } // nullary
+	[int] f( ) { return 3; } // unary
+   
+Current syntax for tuple indexing is an integer constant, where its value
+selects a tuple member, e.g.:
 
 	[char, int] tup;
 	tup = ['a', 0];
-	int value = t.1;
+	char ch = t.0; // select first tuple member
+	int value = t.1; // select second tuple member
 
 ### Mass and Multi-Assignment
 
-Two special forms of assignment can be used to set values in tuples.
-Mass Assignment assigns every element in the tuple to a single source value.
+Two special forms of assignment can be used to set values in tuples: mass and
+multi.  Mass assignment assigns every element in the destination tuple to a
+single source value.
 
 	[int, long, float] dst;
 	int src = 4
-	dst = src;
-	// Expands to roughly: dst.0 = src, dst.1 = src, dst.2 = src
-
-Multi-Assignment assigns every element to the matching element of a source
-tuple (both tuples must be the same size).
-
-	[int, long, float] dst;
-	[int, long, double] src = [1, 20, 300.0];
-	dst = src;
-	// Expands to roughly: dst.0 = src.0, dst.1 = src.1, dst.2 = src.2
-	// Note that the last assignment is not an exact match,
-	// an implicit conversion will be applied.
+	dst = src;  // => dst.0 = src; dst.1 = src; dst.2 = src
+
+Multi-assignment assigns every element in the destination tuple to the
+corresponding element in the source tuple. Both tuples must be the same size
+and the elements assignment compatible => conversions.
+
+	[long, int, float] dst;
+	[int, char, double] src = [1, 'a', 300.0];
+	dst = src;   // => dst.0 = src.0; dst.1 = src.1; dst.2 = src.1
 
 ### Tuple Restructuring
 
 Tuples can be restructured as part of overload resolution. Function calls
-will unpack tuples and repack tuples to match signatures. This is a type of
-implicit conversion and is considered during overload resolution.
+unpack tuples and repack tuples to match signatures. This semantics is a form
+of implicit conversion and is considered during overload resolution.
 
 A simple example is matching multiple parameters of a function to a single
-argument expression, each parameter is bound to a different element of the
-returned tuple.
-
-	[int, int] paramFunc();
-	void callFunc(int a, int b, int c, int d);
-
-	void restructure() {
-		callFunc(paramFunc(), paramFunc());
+argument expression, where each parameter is bound to a different element of
+the returned tuple.
+
+	[int, int] argFunc();
+	void parmFunc(int a, int b, int c, int d);
+
+	parmFunc(argFunc(), argFunc());
+
+	// Roughly equivilent to:
+	[int, int] fst = argFunc();
+	[int, int] snd = argFunc();
+	parmFunc(fst.0, fst.1, snd.0, snd.1);
+
+There are few languages supporting multiple return-values as a standalone
+feature (SETL). Go has multiple return-values but restricts their use in
+matching arguments to parameters.
+
+	func argFunc() (int, int) {
+	    return 3, 7
 	}
-	// Roughly equivilent to:
-	void restructure() {
-		[int, int] fst = paramFunc();
-		[int, int] snd = paramFunc();
-		callFunc(fst.0, fst.1, snd.0, snd.1);
+	func parmFunc( a int, b int ) {
+	     fmt.Println(a, b )
 	}
-
-This is the unique feature of Cforall tuples. There are a few languages with
-multiple return values, but they are usually are a stand alone feature.
+	func main() {
+	     parmFunc2( argFunc() ); // arguments must match exactly with parameters
+	}
 
 ### Tuple Casts
 
 C-style casts can be used on tuples. These are usually conversion casts (casts
-that preform operations on the cast type, as opposed to reinterpreting the
+that perform operations on the cast type, as opposed to reinterpreting the
 existing value).
 
@@ -103,7 +136,7 @@
 	([int, char])x;
 
-This casts the first element type from a char to an int and drops the last
+This casts the first element type of x from a char to an int and drops the last
 element. The second line can be replaced with the following code, which creates
-a new tuple by casting the kept elements of the old tuple:
+a new tuple by directly casting the kept elements of the old tuple:
 
 	[(int)x.0, (char)x.1];
@@ -111,6 +144,12 @@
 Note, tuple casting is more restricted than the implicit tuple restructuring.
 It cannot do any restructuring beyond dropping the trailing elements of
-tuples. For example, you cannot cast `[int, [bool, char], int]` to be a
-`[int, bool, char, int]`.
+tuples. For example,
+
+	int i; char c; bool b;
+	[i, b, c, i] = [i, [b, c], i];
+	[int, [bool, char], int] w;
+	[i, b, c, i] = w;
+	[i, b, c, i] = ([int, bool, char, int])w; // fails
+	[i, b, c] = ([int, [bool, char]])w; // works
 
 ### Polymorphic Tuple Parameters
@@ -121,44 +160,66 @@
 sequence of types.
 
-	forall(T, Ts... | { T max(T, T); T max(Ts); })
+	forall( T | { int ?>?( T, T ); } )
+	T max( T v1, T v2 ) { return v1 > v2 ? v1 : v2; }  // base case
+
+	forall(T, Ts... | { T max(T, T); T max(Ts); })  // recursive case
 	T max(T arg, Ts args) {
 		return max(arg, max(args));
 	}
 
-This introduces a type name into scope. It is used as a type but because the
-tuple is flattened, the second assertion "T max(Ts);" matches types with
-multiple parameters, although it is used as a tuple function inside the
-function body. For example, in the three-argument case (all three of the
-same type), both assertions can match the same function. Then "Ts args"
-introduces args as a tuple, where it is passed to max.
+This feature introduces a type name into scope (Ts). It is used as a type but
+because the tuple is flattened, the second assertion "T max(Ts);" matches types
+with multiple parameters (the `...`), although it is used as a tuple function
+inside the function body (max(args)).
+
+The first non-recursive max function is the polymorphic base-case for the
+recursion, i.e., find the maximum of two identically typed values with a
+greater-than (>) operator.  The second recursive max function takes two
+parameters, a T and a Ts tuple, handling all argument lengths greater than two.
+The recursive function computes the maximum for the first argument and the
+maximum value of the rest of the tuple.  The call of max with one argument is
+the recursive call, where the tuple is converted into two arguments by taking
+the first value (lisp car) from the tuple pack as the first argument
+(flattening) and the remaining pack becomes the second argument (lisp cdr).
+The recursion stops when the tuple is empty.  For example, max( 2, 3, 4 )
+matches with the recursive function, which performs return max( 2, max( [3, 4]
+) ) and one more step yields return max( 2, max( 3, 4 ) ), so the tuple is
+empty.
+
 
 Issues with the Current State
 -----------------------------
-There are a variety of problems with the current implementation which we
-would like to fix.
+There are a variety of problems with the current implementation which need to
+be fixed.
 
 ### Tuples are not Objects
 
-Spoilers, this proposal actually takes them further away from being objects.
-But this illustrates why the current version is not as useful is it could be.
-
-Tuples do not have the lifetime operators (copy construction, copy assignment
-and destructor) and cannot be passed in as a bundle to polymorphic functions.
-The multi-assignment operation is not a single function and is not passed
-in as an assertion.
-
-This prevents tuples from being interwoven with regular polymorphic code.
+Spoilers: this proposal actually takes them even further away from being
+objects, but illustrates why the current version is not as useful is it could
+be.
+
+Because of the fluid nature of tuples (flattening/structuring), routines like
+constructions, destructor, or assignment do not make sense, e.g. this
+constructor matches multiple a tuple types:
+
+	void ?{} ( [int, int, int] ? this );
+	[int, [int, int]] x; // all match constructor type by flattening
+	[int,  int, int]  y;
+	[[int, int], int] z;
+
+as could a similarly typed destructor or assignment operator.  This prevents
+tuples from being interwoven with regular polymorphic code.
 
 ### Providing TType Arguments is Inconsistent
 
-The syntax for ttype arguments is slightly inconsistent. It hasn't come up
-much yet because you do not directly provide ttype polymorphic arguments to
+The syntax for ttype arguments is slightly inconsistent. It has not come up
+much yet, because you do not directly provide ttype polymorphic arguments to
 functions and there are very few existing use-cases for ttype structures.
 
-Passing arguments to a function inlines the arguments,
+Passing arguments to a function inlines the arguments
 while passing them to a polymorphic type requires them to be
 enclosed in a tuple. Compare `function(x, y, z)` with `Type(A, [B, C])`.
 
-This did not come up previously as there was little reason to explicity
+This did not come up previously as there was little reason to explicitly
 provide ttype arguments. They are implicit for functions and there is very
 little use case for a ttype on a struct or union.
@@ -166,12 +227,17 @@
 ### Syntax Conflict
 
-The tuple syntax conflicts with designators and the new attribute syntax.
-These conflicts break C compatibility goals of Cforall. Designators have had
-to their syntax change and Cforall cannot parse the new attributes.
-
-Although most of this redesign is about the semantics of tuples, but an
-update to tuple syntax that removes these conflicts that would improve the
-compatibility of Cforall going forward (and also open up the new attribute
-syntax for cforall features).
+The tuple syntax conflicts with designators and the new C++-style attribute
+syntax.
+
+	struct S { int a[10]; } = { [2] = 3 }; // [2] looks like a tuple
+	[[ unused ]] [[3, 4]]; // look ahead problem
+
+These conflicts break C compatibility goals of Cforall. Designators had to
+their syntax change and Cforall cannot parse the new attributes.
+
+Although most of this redesign is about the semantics of tuples, but an update
+to tuple syntax that removes these conflicts would improve the compatibility of
+Cforall going forward (and also open up the new attribute syntax for cforall
+features).
 
 Change in Model
@@ -181,15 +247,15 @@
 struct tuple is added to cover those cases.
 
-The existing tuples will be even more "unstructured" than they are now.
-Tuples are considered a sequence of types or typed entities. These packs are
-then unpacked into the surrounding context. Put differently, tuples are now
-flattened as much as possible, with some places (like parameter lists) being
-treated as an implicit tuple and the tuple being flattened into that.
-
-Structured tuples are now a separate feature, a structure called "tuple".
-These are polymorphic structures; an instance should act as a structure,
-except that it uses indices instead of field names. These structures shouldn't
-have to be used often, but fill in the use cases that unstructured tuples
-no longer support.
+The new tuples is even more "unstructured" than before.  New tuples are
+considered a sequence of types or typed entities. These packs are then unpacked
+into the surrounding context. Put differently, tuples are now flattened as much
+as possible, with some places (like parameter lists) being treated as an
+implicit tuple and the tuple being flattened into that.
+
+Structured tuples are now a separate feature: a structure called "tuple".
+These are polymorphic structures; an instance should act as a structure, except
+its fields are accessed using indices instead of field names. Experience so far
+is that structured tuples are not used often, but fill in the use cases that
+unstructured tuples no longer support.
 
 Note that the underlying implementation might not actually look like this.
@@ -201,28 +267,24 @@
 ### Structured Tuple Type
 
-There are still use cases for a structured tuple type. The issues in
-supporting both were because there was one feature trying to support both
-uses. Hence, it is added back in as its own feature.
-
-There should be a standard library or built-in type named `tuple`, it doesn't
-need a special syntax to write types or instances. The type definition might
-use some primitive support, but if supported as a regular type would look
-something like this:
+There is a standard library or built-in type named `tuple`, it does not need a
+special syntax to write types or instances. The type definition might need some
+primitive support, but if supported as a regular type would look something like
+this:
 
 	forall(Ts...)
 	struct tuple {
-		inline Ts all;
+		inline Ts all; // inline all specified fields
 	};
 
-This will be constructed the same way as most types, a list initializer with
-each tuple argument, and the lifetime functions (copy construction, copy
-assignment and destruction) work the same. Field access works two ways, the
-first is accessing the all field, effectively converting the structured
-"struct" tuple into an unstructured tuple, the other is to use tuple indexing
-directly on the structure as if it was an unstructured tuple.
-
-(If inline doesn't work, just rename all to `get`. It does make things a bit
-longer but has no change in functionality. If the all access doesn't work,
-that is a bit more of a problem, tuple slicing might provide a work around.)
+This type is constructed the same way as most types, a list initializer with
+each tuple argument, and the lifetime functions (construction, assignment and
+destruction) work the same. Field access works two ways, the first is accessing
+the `all` field, effectively converting the structured tuple into an
+unstructured tuple, the other is to use tuple indexing directly on the
+structure as if it is an unstructured tuple.
+
+(If `inline` does not work, just rename all to `get`. It does make things a bit
+longer but has no change in functionality. If the `all` access does not work,
+that is more problematic, and tuple slicing might provide a work around.)
 
 ### Type Qualifier Distribution
@@ -233,12 +295,13 @@
 the tuple.
 
-Previously `[int, bool] &` would mean a reference to a tuple of an integer
-and a boolean. Now it would be an alias for `[int &, bool &]`, a tuple of a
-reference to an integer and a reference to a boolean. This also applies to
-polymorphic tuple type packs `Ts &` in polymorphic functions.
-
-This allows to specify restrictions on types as you would with a single
-type variable. For example, this can help replace the special cased
-tuple operations, multi-assignment (N-to-N) and mass-assignment (1-to-N).
+Previously `const [int, bool] &` would mean a const reference to a tuple of an
+integer and a boolean. Now it means an alias for `[const int &, const bool &]`,
+a tuple of a reference to a constant integer and a reference to a constant
+boolean. This also applies to polymorphic tuple type packs `Ts &` in
+polymorphic functions.
+
+This new approach can specify restrictions on tuple variables as for a single
+type variable. For example, this approach can replace the special cased tuple
+operations multi-assignment (N-to-N) and mass-assignment (1-to-N).
 
 	// Multi-Assignment
@@ -269,14 +332,14 @@
 ### Type Packs
 
-This is not a new feature, but a reframing/extension of existing tuple tuple
-polymorphic parameters as polymorphic type packs. The `Vars...` syntax
-introduces a pack of types into scope. It can be used in many of the same
-ways as a tuple, but in some new ways to.
-
-The primary existing use remains; you can use a polymorphic pack in a
-parameter list, both as part of an assertion and in the signature of the
-main function. The difference is that this is not an enclosed tuple, but
-a series of types. The only effective difference this makes is it doesn't
-prefer to match another tuple/pack.
+This approach is not a new feature, but a reframing/extension of existing tuple
+tuple polymorphic parameters as polymorphic type packs. The old `Vars...`
+syntax introduces a pack of types into scope. It can be used in much the same
+way as a tuple, but in some new ways to.
+
+The primary existing use remains: to use a polymorphic pack in a parameter
+list, both as part of an assertion and in the signature of the main
+function. The difference is that this is not an enclosed tuple, but a series of
+types. The only effective difference this makes is it does not prefer to match
+another tuple/pack.
 
 This pattern continues to a parameter defined with a pack of types, which
@@ -287,6 +350,6 @@
 	void function(Params values);
 
-New use cases include declarations of members and variables. For example,
-the creation the structured tuple structure:
+New use cases include declarations of members and variables. For example, the
+creation of a structured tuple structure:
 
 	forall(Fields...)
@@ -320,5 +383,5 @@
 
 Declaring a tuple acts as a pack of variable declarations. When this is done
-with written out type (as opposed to a polymorphic parameter above), then the
+with a written out type (as opposed to a polymorphic parameter above), then the
 elements of the tuple can be named.
 
@@ -333,4 +396,6 @@
 no named to access it.
 
+PAB: I do understand the point of this.
+
 ### Tuple Casts
 
@@ -344,5 +409,5 @@
 The unstructured tuple cannot represent all the types that the previous
 semi-structured tuple could. These cases still exist in various ways,
-special in the internals of a polymorphic type, but in general should be
+specifically in the internals of a polymorphic type, but in general should be
 considered in their reduced form.
 
@@ -350,10 +415,10 @@
 conflicts that currently exist.
 
-Nullary, or 0 element tuples, are equivlent to void, the type that carries
+Nullary, or 0 element tuples, are equivalent to void, the type that carries
 no data, because they do not either. It should either be replaced with void
 or removed entirely when it appears in a larger sequence.
 
 	// For example, this function:
-	forall(Ts...) Ts example(int first
+	forall(Ts...) Ts example(int first, ????)
 	// With Ts = [], should not be treated as:
 	[] example(int first, [] middle, int last);
@@ -364,12 +429,12 @@
 is to say a single type in an unstructured tuple is a no-op.
 
-Lastly, nested tuples are always flattened into to form a one-deep tuple.
-This means that `[bool, [char, int], float]` is resolved as
-`[bool, char, int, float]`, with the internal structure of the tuple ignored.
-
-The flatten into a large sequence rule mentioned above, is actually just an
-application of this. Unstructured tuples can already be restructured, even
-at the top level of an function call. This can be expressed by considering
-the argument list as a tuple:
+Lastly, nested tuples are always flattened to a one-depth tuple.  This means
+that `[bool, [char, int], float]` is resolved as `[bool, char, int, float]`,
+with the internal structure of the tuple ignored.
+
+The flatten into a large sequence rule mentioned above is actually just an
+application of this. Unstructured tuples can already be restructured, even at
+the top level of an function call. This can be expressed by considering the
+argument list as a tuple:
 
 	call(false, ['a', -7], 3.14)
@@ -385,17 +450,25 @@
 (Disclaimer: this is a bit more impulsive, see end for notes.)
 
-This is an extension to tuple indexing. Currently, you may index single
-location of a tuple, extracting the element at that location. By extending
-the index expression to be a range we can grab a slice of the existing tuple
-as another smaller tuple.
-
-	[int_x, char_y] = [int_a, char_b, double_c].(0+~=1)
-
-To get the new tuple, the range has to be constructed and traversed at
-compile time. The size of the range is the size of the result tuple, with
-each element in the result tuple decided by the matching element of the
-range, which gives the index of the original tuple to place there.
-The type of the indices may be and integral type, but all indices must be in
-range, otherwise it is a compile time error.
+This is an extension to tuple indexing. Currently, only single location of a
+tuple can be index, extracting the element at that location. By extending the
+index expression to be a list-range a multiple sub-tuples can be extracted.
+
+	[0, 1, 2, 3, 4, 5, 6, 7, 8, 9].0~2,5~9~2
+
+produces the tuple
+
+	[0, 1, 2, 5, 7, 9]
+
+(Note the position and values are the same to simplify the example.) That is,
+index the first 3 tuple elements, and then indexes elements 5 to 9 in steps of
+2. Not all selections are possible with this mechanism (e.g., index the
+Fibonacci elements), but it covers many cases.
+
+To get the new tuple, the range has to be constructed and traversed at compile
+time. The size of the range is the size of the result tuple, with each element
+in the result tuple decided by the matching element of the range, which gives
+the index of the original tuple to place there.  The type of the indices may be
+an integral type, but all indices must be in range, otherwise it is a compile
+time error.
 
 In terms of the existing range loops, if you could write this dynamically, it
@@ -410,5 +483,5 @@
 as indexing the single value in the range.
 
-Some closing notes, this is dependent on generalised range expressions.
+Some closing notes, this is dependent on generalized range expressions.
 The iterators proposal has a section on some new range types, this feature
 is intended to be built on that feature. Not simply reuse some of the syntax
@@ -416,4 +489,7 @@
 need to be improved.
 
+PAB, I don't understand this last part as the index range is compile time not
+runtime.
+
 Implementation
 --------------
@@ -421,7 +497,16 @@
 
 ### Structured Tuple Implementation
-Under the hood, unstructured tuples will probably just be implemented as
-structured tuples, with the restructuring code inserted wherever needed.
-In short, the base implementation should stay mostly the same.
+
+Under the hood, unstructured tuples are implemented as structured tuples, with
+the restructuring code inserted wherever needed.  In short, the base
+implementation should stay mostly the same.
+
+PAB: The current implementation does not use convert unstructured tuples to
+structured tuples. Look at the code generated for
+
+	int x, y;
+	[x, y] = 3;
+	[x, y] = [y, x];
+
 
 Actually inlining tuples can be done in some cases, it may even help with
@@ -431,4 +516,5 @@
 
 ### AST Updates
+
 The current AST cannot represent all the new features. Particularly, an
 object declaration cannot name elements of the tuple. To this end a new
@@ -438,6 +524,12 @@
 This would act much like a `FunctionDecl` except for tuples, narrowing the
 possible types, to `TupleType` instances instead of `FunctionType` instances,
-and storing some additional information, in this case the names of the
+and storing some additional information. In this case, the names of the
 elements of the tuples.
+
+PAB: the following parses:
+
+	[int x, int y] foo( int p );
+
+and discussed by Till.
 
 (I'm not actually going to decide the implementation now, but some early
@@ -446,8 +538,9 @@
 
 ### Field Packs
-Field packs in structures will probably have to be written out in full by
-the specialization pass. If they are not, it could have some negative effects
-on layout, causing a structure to take up extra space. It may be able to
-reuse some of the specialization code for the existing tuples.
+
+Field packs in structures probably have to be written out in full by the
+specialization pass. If not, it could have some negative effects on layout,
+causing a structure to take up extra space. It may be able to reuse some of the
+specialization code for the existing tuples.
 
 Related Features in Other Languages
@@ -461,9 +554,10 @@
 There are many languages with structured tuples. Usually just called tuples,
 but they usually follow the same rules as a polymorphic anonymous structures,
-that is to say you provide N types to create a new N-arity tuple. They also
+that is to say N types are provided to create a new N-arity tuple. They also
 usually have some special syntax to index the tuples, because there are no
-field names to use.
+field names.
 
 #### Rust
+
 Rust has the standard tuples as a primitive in the language. Each arity of
 tuple is a different polymorphic type.
@@ -483,6 +577,6 @@
 
 Some tuple features only apply up to 12-arity tuples.
-It is not directly stated, but I believe the difference is the more limited
-features are implemented in the standard library, for each arity of tuple.
+It is not directly stated, but I believe the difference in the more limited
+features are implemented in the standard library, one for each arity of tuple.
 
 -   https://doc.rust-lang.org/std/primitive.tuple.html
@@ -490,5 +584,6 @@
 -   https://doc.rust-lang.org/reference/expressions/tuple-expr.html
 
-#### C++
+#### C++ tuple
+
 Implemented as a template type defined in the standard library. No special
 language features exist to support this, due to the power of C++'s template
@@ -500,6 +595,6 @@
 types. This is the standard notation for template type instances.
 
-There is no special syntax for member access of a tuple. You have to use a
-template function, for example `std::get<0>( tuple )`.
+There is no special syntax for member access of a tuple. A template function is
+used, e.g., `std::get<0>( tuple )`.
 
 C++ also has structured binding, a kind of limited pattern matching. In a
@@ -511,111 +606,9 @@
 -   https://en.cppreference.com/w/cpp/language/structured_binding
 
-#### Haskell
-Haskell has a special syntax for tuples, but otherwise they are completely
-normal polymorphic types. Because of this, tuples have a maximum size.
-Haskell (98) supports tuples of up to 15 elements and the standard library
-has functions for tuples of up to 7 elements.
-
-The syntax for tuples is a comma separated list of elements. Either element
-types to create a tuple type, or element values to create a tuple value. The
-context decides which one we are looking for. Such as `(6, "six")` or
-`(Bool, Char, Int)`.
-
-You can also remove all the elements, getting an expression like "(,)" or
-"(,,,)", which can be then be used as a function, for a type or expression.
-
-Haskell supports pattern matching as the main way to extract values from a
-tuple, although helper functions "fst" and "snd" are provided for field
-access on two element tuples.
-
-Haskell does not have 0 or 1-element tuples. The nil type, written "()" for
-both type and value, is effectively the 0 element tuple. There is also a type
-called "Solo" that is a polymorphic structure with one field and is used as
-the 1-element tuple, but has regular Haskell data type syntax.
-
--   https://www.haskell.org/onlinereport/basic.html
-
-#### OCaml
-OCaml only supports multi-element (2 or more) tuples. Tuple types are written
-as a '*' separated list of types, tuple values are written as ',' separated
-list of expressions. Pattern matching tuples is supported and uses the same
-syntax as values. Parenthesizing these lists is only needed for grouping.
-
-OCaml does not support 0 or 1 element tuples. It does however have the `unit`
-type which has one value, written `()`.
-
--   https://ocaml.org/docs/basic-data-types#tuples
-
-#### Swift
-Swift has tuple types that use the basic parenthesized, comma
-separated list of types or values. It only supports 0 and 2 or more element
-tuples (the `Void` type is an alias for the empty tuple type).
-
-Swift also supports named tuples. Names can be added to before the tuple
-element, both for the tuple type and value. The syntax is a name followed by
-a colon, for example `(first: int, second: int)`. These names are a fixed
-part of the type, and can be used as part of field access notation (otherwise
-numbers are used in-place of field names `tuple.0` vs. `tuple.first`).
-
--   https://docs.swift.org/swift-book/documentation/the-swift-programming-language/types/#Tuple-Type
-
-#### Python
-In Python tuples are immutable lists. Because they are dynamically typed
-there is only one tuple type `tuple`.
-
-It also has various named tuples. The first, namedtuple, just allows you to
-add a name the elements of the tuple. The second, NamedTuple, is actually a
-way of creating a typed record in a normally untyped language.
-
--   https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range
--   https://docs.python.org/3/library/collections.html#collections.namedtuple
--   https://docs.python.org/3/library/typing.html#typing.NamedTuple
-
-#### LISP
-As LISP is dynamically typed, its cons data type is an untyped pair and is
-(perhaps infamously) the main constructor of all compound data types.
-The function `cons` takes two arguments and builds a pair. Functions `car`
-and `cdr` get the first and second elements of the pair.
-
-### Packs
-
-Packs (or unstructured tuples) are a much less common feature. In fact, there
-might just be one language, C++, that supports packs. The most common use
-case for unstructured tuples is returning multiple values, so there is a
-comparison to languages that have that as a special feature.
-
-#### Go
-Go does not have built in tuple types, but it has multi-return syntax that
-looks like the tuple syntax of many other languages.
-
-```
-func main() {
-	i, j := returnIntInt()
-	...
-}
-
-func returnIntInt() (int, int) {
-	return 12, 34
-}
-```
-
--   https://golangdocs.com/functions-in-golang
--   https://go.dev/src/go/types/tuple.go
-
-#### Lua
-Lua is a scripting language, is dynamically typed and stack based. Although
-the stack usually only directly visible in the C-API, it does allow any
-function to return any number of values. Even in a single return, if the
-return expression
-
-```
-local funcion f()
-	return 12, 34
-end
-
-local i, j = f()
-```
-
-#### C++
+PAB: I do not understand the syntax `auto [first, second]`. Where does it come
+from?
+
+#### C++ template
+
 C++ templates can take various types of parameters, including parameter
 packs. These contain series of values. These are used in pack expansion,
@@ -659,2 +652,108 @@
 -   https://en.cppreference.com/w/cpp/language/parameter_pack
 -   https://en.cppreference.com/w/cpp/language/fold
+
+#### Haskell
+
+Haskell has a special syntax for tuples, but otherwise they are completely
+normal polymorphic types. Because of this, tuples have a maximum size.
+Haskell (98) supports tuples of up to 15 elements and the standard library
+has functions for tuples of up to 7 elements.
+
+The syntax for tuples is a comma separated list of elements. Either element
+types to create a tuple type, or element values to create a tuple value. The
+context decides among them, such as `(6, "six")` or `(Bool, Char, Int)`.
+
+Also all the elements can be removed, getting an expression like "(,)" or
+"(,,,)", which can be then be used as a function, for a type, or an expression.
+
+Haskell supports pattern matching as the main way to extract values from a
+tuple, although helper functions "fst" and "snd" are provided for field
+access on two element tuples.
+
+Haskell does not have 0 or 1-element tuples. The nil type, written "()" for
+both type and value, is effectively the 0 element tuple. There is also a type
+called "Solo" that is a polymorphic structure with one field and is used as
+the 1-element tuple, but has regular Haskell data-type syntax.
+
+-   https://www.haskell.org/onlinereport/basic.html
+
+#### OCaml
+
+OCaml only supports multi-element (2 or more) tuples.  It does have the `unit`
+type, which has one value, written `()`. Tuple types are written as a '*'
+separated list of types, tuple values are written as ',' separated list of
+expressions. Pattern matching tuples is supported and uses the same syntax as
+values. Parenthesizing these lists is only needed for grouping.
+
+-   https://ocaml.org/docs/basic-data-types#tuples
+
+#### Swift
+
+Swift has tuple types that use the basic parenthesized, comma separated list of
+types or values. It only supports 0 and 2 or more element tuples (the `Void`
+type is an alias for the empty tuple type).
+
+Swift also supports named tuples. Names can be added before the tuple element,
+both for the tuple type and value. The syntax is a name followed by a colon,
+e.g., `(first: int, second: int)`. These names are a fixed part of the type,
+and can be used as part of field access notation (otherwise numbers are used
+in-place of field names `tuple.0` vs. `tuple.first`).
+
+-   https://docs.swift.org/swift-book/documentation/the-swift-programming-language/types/#Tuple-Type
+
+#### Python
+
+In Python tuples are immutable lists. Because they are dynamically typed,
+there is only one tuple type `tuple`.
+
+It also has various named tuples. The first, namedtuple, allows naming the
+elements of the tuple. The second, NamedTuple, is actually a way of creating a
+typed record in a normally untyped language.
+
+-   https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range
+-   https://docs.python.org/3/library/collections.html#collections.namedtuple
+-   https://docs.python.org/3/library/typing.html#typing.NamedTuple
+
+#### LISP
+As LISP is dynamically typed, its `cons` data type is an untyped pair and is
+(perhaps infamously) the main constructor of all compound data types.  The
+function `cons` takes two arguments and builds a pair. Functions `car` and
+`cdr` get the first and second elements of the pair.
+
+### Packs
+Packs (or unstructured tuples) are a much less common feature. In fact, there
+might just be one language, C++, that supports packs. The most common use
+case for unstructured tuples is returning multiple values, so there is a
+comparison to languages that have that as a special feature.
+
+#### Go
+Go does not have built in tuple types, but it has multi-return syntax that
+looks like the tuple syntax of many other languages.
+
+```
+func main() {
+	i, j := returnIntInt()
+	...
+}
+
+func returnIntInt() (int, int) {
+	return 12, 34
+}
+```
+
+-   https://golangdocs.com/functions-in-golang
+-   https://go.dev/src/go/types/tuple.go
+
+#### Lua
+Lua is a scripting language that is dynamically typed and stack based. Although
+the stack is usually only directly visible in the C-API, it does allow any
+function to return any number of values, even a single return, in the return
+expression
+
+```
+local funcion f()
+	return 12, 34
+end
+
+local i, j = f()
+```
