DIP54 : revamp of Phobos tuple types

Jakob Ovrum jakobovrum at gmail.com
Mon Dec 30 00:46:51 PST 2013


On Sunday, 29 December 2013 at 21:41:48 UTC, Dicebot wrote:
> Of course because we have damn nothing in our template 
> algorithm set. Those are just basics. If stuff goes as planned 
> std.meta.* will have template alternatives of almost all stuff 
> from std.range and std.algorithm. Any function from there that 
> takes pair of ranges or range of ranges will be subject to this 
> decision. Should I list them all?

Packed lists only come into play with algorithms that receive a 
list of lists that can contain types (for non-types we'd be in 
good shape with `toTypeTuple`). Again, I've never had a use for 
this, so I expect the DIP to adequately explain the motivation 
behind going to such great lengths to support it. It doesn't do 
this at all. Not a single example or reference or anything.

> You words about "huge maintenance cost" are pretty much as 
> subjective and unproved as my "it is ugly" statement. If 
> anything, packed lists result in easier maintenance as they 
> make list passing more hygienic and in line with passing of any 
> other aliases and flattening/merging of lists explicit and 
> obvious. There has been one guy even in this thread who was 
> surprised by current behavior.

My statement assumed that existing (and maybe new) algorithms 
would support *both* plain argument lists like they do now, and 
packed lists.

If we instead choose only plain argument lists, no changes are 
required. If we instead choose only packed lists, there is a 
one-time cost to porting all the algorithms, but no extra 
maintenance cost from then on out.

> And built-in variadic templates will remain anyway, so question 
> is not "what merit auto-expanding list does have" but "what 
> merit auto-expanding list does have as an extra library type".

I don't think it's correct nor useful to refer to template 
argument lists as "types", or that std.typetuple.TypeTuple is 
somehow a type. A packed list implemented through a *struct* with 
AliasThis would be a type, although a pretty terrible one. Its 
use as a type would be valid but complete nonsense; it's only a 
struct for its function as a namespace.

>>> New multilist utilities added are expected to use `Pack`s (I 
>>> am still convinced that using nested templates for that is 
>>> ugly)
>>
>> I don't consider "it's ugly" with no elaboration a valid 
>> argument.
>
> "It is completely out of line with existing function signatures 
> for non-template algorithms that it mirrors"

It's essentially currying, which is no surprise considering the 
functional nature of templates. It also has the advantage of 
allowing "partial template instantiation".

I also don't think there's any point in emulating manipulation of 
values for manipulation of types when functions and templates are 
in reality different.

> "Use for declaring an expression list from a type list" - not 
> common at all and pretty much never used by anyone but very 
> experienced library writers (it is rather arcane thing on its 
> own)

It's *the* most common use of variadic templates, hands down:

---
void write(Args...)(Args args)
{
     // `Args` is a type list, `args` is an expression list
}
---

> "Use for initalizing other expressions lists with an expression
> list" - should require expansion anyway because it is how 
> std.typecons.Tuple works

Consider this kind of code, which I often see in the wild, even 
by relative beginners who are eager to learn about D's generative 
abilities:

---
ParameterTypeTuple!fun args;

foreach (ref arg; args)
     arg = strArgs.parse!(typeof(arg));

fun(args);
---

Packed lists would just be in the way here. If you try to fix 
that problem with AliasThis, you gain another problem - 
especially if `fun` is a function template!

> "Use in static foreach" - works with alias this

The AliasThis approach has issues. We need more experience with 
it if we want to pursue packed lists.

> "Use in special expressions that operate on types, such as `is`,
> `typeof` and `typeid`" - any code that does on expanded lists 
> right now is completely broken and must be re-written according 
> to existing spec. Exanded argument list is not a valid type for 
> any of those entities (despite it is magically accepted). 
> Indexing single element works with "alias this".

They are documented on the tuple page and it is not "magical" 
that it is accepted; it is deliberate. It is clearly illustrated 
in one of the examples there, and the behaviour is definitely 
useful. Again, don't confuse template argument lists for being 
"types". That's not a useful definition for anyone.

> "Use as a public alias in a library interface, leaving the
> specifics of application to the user" - irrelevant to expansion 
> as you mention on your own

It's just for completeness. I believe the list is complete now 
that you have added indexing.

> Yep, this is an attempt to somewhat compensate bad language 
> decision by more hygienic library solution. Your rationale is 
> based on assumption that language feature is OK an anything 
> else should be based on it. But it is not OK in general, only 
> for very few library writers.

I think it's OK, also for beginners. If you want to convince 
people that it's not, you need to come up with a solid rationale 
that illustrates how the language semantics are bad. Again, I 
believe we have a naming and documentation problem.

> My key point is that common and basic use cases that are likely 
> to appear in casual code should take priority over needs of 
> library writers as latter are ready to deal with extra 
> complexity pretty much by definition. I am personally ready to 
> do it despite it will cause problems/inconvenience for my own 
> code. simply because it is bigger than that. Your arguments 
> about use cases are very biased towards that librar'ish usage. 
> We don't have any hard stats here so someone else needs to make 
> the judgement but I think you are mistaken in how widely 
> applicable it is.

My arguments are rooted in language semantics (that you are 
desperately fighting). They apply to all users of template 
argument lists, however casual.

>> expansion is the only use case of template argument lists.
>
> You keep repeating it and have not shown strong evidences for 
> it so far. Core use cases for template arguments in common user 
> code is indexing and iteration which can "just work" for packs 
> too.

I listed a complete list of all use cases of template argument 
lists, and they all require expansion. I think that's strong 
evidence.

Yes, static foreach and indexing can work with AliasThis, but 
again, the struct + AliasThis has issues (and how is indexing a 
template argument list a casual use, btw?).

> If we won't address this question at the same time it will pop 
> up again once std.meta.* pull request will start to appear and 
> deferring decision to that point will just force users to 
> adjust same code twice. That does not sound good.

Better than predicating the entire conversation on the unproven 
thesis that std.meta.* will not only be accepted, but will 
completely eclipse all use of template argument lists, which I 
don't think it will even come close to do. Attempting to do so, 
will - as I've argued - harm (all) users of template argument 
lists in the common case.


More information about the Digitalmars-d mailing list