September 11
On Wednesday, 11 September 2019 at 09:58:58 UTC, jmh530 wrote:
>
> I'm not a compiler expert or anything, so I didn't go through every little piece of the DIP initially in order to try to grok how it worked. I don't have a good sense of how the compiler currently resolves templates, so trying to understand how it worked in this specific case seemed like a big hill to climb.
>

For me, this DIP is the most complicated DIP I have seen - _just_ to handle
alias declarations / instatiations in function arguments.
And it already takes a lot of things for granted (i.e. the `Gen`
function in the DIP is not specified). I would not have been
able to complete it without some help from one of my professors.

What I mean is that this is not necessarily the easiest thing
to understand and even if it was, I'm not an expert in writing
formal specifications.

Regarding the implementation, well.. this a particularly draft
implementation. :P It is after 3 days of first opening DMD.

> The reason why I was talking about the explicit template syntax is because it provides a lot of flexibility.
>
> When talking about Atila's concepts library above, the thing that is in the back of my mind is something like isInputRange (he provides an example in the Readme.md). One issue with passing an input range to a lot of phobos functions is that if you pass something that isn't an input range the error message isn't specific about why it isn't an input range. For instance, did you forget to define popFront? The concepts library helps provide better error messages in this case. However, it currently requires you to use @models at the top of the struct in order to check this information. This requires the user to put models UDA before their own struct, rather than this happening at the point of the function. If we were able to do something like below, then the user does not need to put it on their own structs. I think that would make the concepts library much more powerful.
>
> template InputRange(T) {
>     import concepts: models, isInputRange;
>     static assert(models!(Foo, isInputRange));
>     alias InputRange = T;
> }
>
> void useInputRange(T)(InputRange!T foo) {
>
> }

I understand the reasoning, yes. I also think it would be very beneficial.
The problem is that throwing templates in general into the mix I think
will make the DIP way complicated. Also, I don't think I will be able
to derive a formal specification.

Btw, IMHO, templates are in general under-specified. Both in D and C++.
I might have missed something but to the best of my knowledge, they're
constrained to intuitive descriptions and examples. Especially considering
the C++'s `using`. And then it is left to the compiler implementor
to get to a specific behavior.

I tried this DIP to provide a formal specification for the subject. And I'm
here to answer questions and receive corrections as I understand this is
not necessarily the best formal specification ever.

- Stefanos
September 11
On Wednesday, 11 September 2019 at 12:11:21 UTC, Stefanos Baziotis wrote:
> [snip]
>
> I understand the reasoning, yes. I also think it would be very beneficial.
> The problem is that throwing templates in general into the mix I think
> will make the DIP way complicated. Also, I don't think I will be able
> to derive a formal specification.

Even if it's too complicated to support the use case I described above as part of this DIP, I still think this has a lot of value.

Another reason I brought up that potential use case is that if it enabled that pattern then it might have helped convince Atila the DIP was a good idea if he could see the benefits with respect to one of his libraries.

>
> Btw, IMHO, templates are in general under-specified. Both in D and C++.
> I might have missed something but to the best of my knowledge, they're
> constrained to intuitive descriptions and examples. Especially considering
> the C++'s `using`. And then it is left to the compiler implementor
> to get to a specific behavior.
>

I'm sure people would appreciate any enhancements to the D specification.
September 11
On 11.09.19 13:49, Stefanos Baziotis wrote:
> On Wednesday, 11 September 2019 at 05:32:22 UTC, ag0aep6g wrote:
>> A "template alias" is nothing but a (simple) template that resolves to an alias.
>>
>> This:
>>     alias Foo(T) = ...;
>> is just short for this:
>>     template Foo(T) { alias Foo = T; }
>> They are exactly the same thing to the compiler.
> 
> We should be more precise here. 2 things that are semantically the same
> might not be the same for the compiler (and the compiler's job is to handle
> them as the same).

Ok, sure. The difference is in syntax. It's the compiler's job to interpret the shorthand variant exactly like the longhand.

> A trivial example is this:
> ```
> alias my_int = int;
> 
> my_int x;
> ...
> ```
> 
> my_int and int are semantically exactly the same, but to the compiler they're
> not. The compiler has to do work to handle them as the same.

And it might make sense to focus on that difference if you're writing a DIP that changes the meaning of `alias`. But if you're writing a DIP that changes the meaning of `int`, then we expect that is also applies to `my_int`.

So unless your DIP states that it changes the meaning of the alias template shorthand syntax, we expect that it also works with the longhand.

> I'm not saying that in your example they are or not, because I don't know / remember. You might do though.
> But this is an important distinction. As far as I remember, they're
> not handled as the same and I wouldn't think that they're handled the same
> as well.

As far as I understand, you suspect a semantic difference. If that's so, you're simply mistaken.

> As another point, and this is the only important thing to a DIP (aka formal
> specification): 2 things might be semantically the same but not formally
> the same. The example above is in that category. The one is an alias declaration
> and the other a built-in type. But the specification should say that they
> should be handled the same.

I'm not sure what "formally the same" would entail. Syntactically, the two variants are different (obviously). But that's it. Semantically, the shorthand is defined to mean whatever the longhand means [1].

> As far as I'm concerned, your example is a template declaration that resolves
> to an alias declaration, which is different from an alias declaration.

Syntactically, `template Foo(T) { alias Foo = T; }` is called a "TemplateDeclaration". Semantically, it declares a template.

Syntactically, `alias Foo(T) = T;` is called an "AliasDeclaration". Semantically, it also declares a template. It doesn't declare an alias.


[1] https://dlang.org/spec/template.html#alias-template
September 11
On Wednesday, 11 September 2019 at 12:47:45 UTC, jmh530 wrote:
> Even if it's too complicated to support the use case I described above as part of this DIP, I still think this has a lot of value.
>

I agree!

> Another reason I brought up that potential use case is that if it enabled that pattern then it might have helped convince Atila the DIP was a good idea if he could see the benefits with respect to one of his libraries.

While that's probably true, IMO both parties
(i.e. the DIP author and the reviewer) should act objectively.
Meaning, a use case of a reviewer should be no different
than another use case.

> I'm sure people would appreciate any enhancements to the D specification.

I agree! I would for sure. And I think compiler implementors as well.

- Stefanos
September 11
On Wednesday, 11 September 2019 at 14:14:31 UTC, ag0aep6g wrote:
> And it might make sense to focus on that difference if you're writing a DIP that changes the meaning of `alias`. But if you're writing a DIP that changes the meaning of `int`, then we expect that is also applies to `my_int`.

It doesn't change the meaning of alias. It changes how
an alias declaration / instantiation acts.

>
> So unless your DIP states that it changes the meaning of the alias template shorthand syntax, we expect that it also works with the longhand.
>

It does as far as I'm concerned. It always states alias
declarations [1] and template alias instantiations
with regard to alias declarations.
The "longhand" version is not an alias declaration, it
is a template declaration.

>
> As far as I understand, you suspect a semantic difference. If that's so, you're simply mistaken.

Firstly, there are things to consider regarding the handling
inside the compiler. Although that has to do with
the implementation, which I don't think we should focus on.

The thing is, semantics is about what something means.
But, regarding formal specifications, there's another
important topic. Actually, the most important for this DIP,
which is how something is resolved to be a specific semantic
entity.
The "longhand" and "shorthand" versions are semantically the same,
i.e. they correspond to the same semantic entity, but the way
one arrives to this entity is different. Meaning, the rules
applied.
And one should consider that. Otherwise, the burden
is left to the compiler implementor.

> I'm not sure what "formally the same" would entail. Syntactically, the two variants are different (obviously). But that's it. Semantically, the shorthand is defined to mean whatever the longhand means [1].

As I said above, in the way I understand it, one thing representing
the same with another is not enough. If that was so, this DIP
would not even be needed since most of its work is to describe
the resolution procedure.

>
> Syntactically, `template Foo(T) { alias Foo = T; }` is called a "TemplateDeclaration". Semantically, it declares a template.
>
> Syntactically, `alias Foo(T) = T;` is called an "AliasDeclaration". Semantically, it also declares a template. It doesn't declare an alias.

Yes, but they're different. Again, going to what I said above.
September 11
On Wednesday, 11 September 2019 at 15:36:04 UTC, Stefanos Baziotis wrote:
> [snip]
>
> While that's probably true, IMO both parties
> (i.e. the DIP author and the reviewer) should act objectively.
> Meaning, a use case of a reviewer should be no different
> than another use case.
>


On this PR thread [1], Atila said he struggled to see the value in it. My objective was to think up an example where he would see the value. I don't dispute that Atila both should and would act objectively in reviewing the DIP. However, if someone says they don't see value in something, it can be helpful to provide additional examples that might show the value.

[1] https://github.com/dlang/dmd/pull/9778
September 11
On Wednesday, 11 September 2019 at 15:52:18 UTC, jmh530 wrote:
> On this PR thread [1], Atila said he struggled to see the value in it. My objective was to think up an example where he would see the value. I don't dispute that Atila both should and would act objectively in reviewing the DIP. However, if someone says they don't see value in something, it can be helpful to provide additional examples that might show the value.

Yes, thank you for that. I agree and I also assume that Atila
will review this objectively. And if supporting this does not complicate
the DIP significantly, it may as well be added.

- Stefanos


September 11
On 11.09.19 17:48, Stefanos Baziotis wrote:
> On Wednesday, 11 September 2019 at 14:14:31 UTC, ag0aep6g wrote:
[...]
>> So unless your DIP states that it changes the meaning of the alias template shorthand syntax, we expect that it also works with the longhand.
>>
> 
> It does as far as I'm concerned. It always states alias
> declarations [1] and template alias instantiations
> with regard to alias declarations.
> The "longhand" version is not an alias declaration, it
> is a template declaration.

So you intend to introduce a difference between shorthand and longhand alias templates?

That's awful. To me, that would be a reason to reject the DIP.

[...]
> Firstly, there are things to consider regarding the handling
> inside the compiler. Although that has to do with
> the implementation, which I don't think we should focus on.
> 
> The thing is, semantics is about what something means.
> But, regarding formal specifications, there's another
> important topic. Actually, the most important for this DIP,
> which is how something is resolved to be a specific semantic
> entity.
> The "longhand" and "shorthand" versions are semantically the same,
> i.e. they correspond to the same semantic entity, but the way
> one arrives to this entity is different. Meaning, the rules
> applied.
> And one should consider that. Otherwise, the burden
> is left to the compiler implementor.

If I understand correctly, you're saying that you want to consider ease of implementation in the compiler.

That's fine. But:

1) It's not obvious that you're actually simplifying the implementation by restricting the feature to the shorthand syntax. Your prototype implementation seems to work just fine with the longhand syntax.

2) Even if it happens to be easier to implement, you have to weigh that against adding a surprising special case to the language. I don't think it's going to be a net positive.
September 11
On Wednesday, 11 September 2019 at 17:53:06 UTC, ag0aep6g wrote:
>
> So you intend to introduce a difference between shorthand and longhand alias templates?
>

Not necessarily. But let's say I do (as it seems the DIP
does currently) for the rest of this and I will discuss the
alternative I'm thinking in the end.

> That's awful. To me, that would be a reason to reject the DIP.
>

Indeed. :/
When I wrote this DIP, I hadn't thought about the long-hand
version. That may seem quite naive, but consider that I was
quite new to D and the use cases I was presented then
were using only the short-hand version. FWIW, this DIP and its
use cases / needs were not mine. But I liked the idea and
did the authoring.

>
> If I understand correctly, you're saying that you want to consider ease of implementation in the compiler.
>

Not necessarily. That would be good but I'm more concerned
about the complexity and clarity of the DIP.

> That's fine. But:
>
> 1) It's not obvious that you're actually simplifying the implementation by restricting the feature to the shorthand syntax. Your prototype implementation seems to work just fine with the longhand syntax.
>

Indeed it's not obvious.

> 2) Even if it happens to be easier to implement, you have to weigh that against adding a surprising special case to the language. I don't think it's going to be a net positive.

Indeed.


So, the alternative:
My first thought is being more high level.
That is, currently the DIP is restricted to alias declarations,
while we can have the same exact semantic entity using a
different type of declaration. This has a lot of subtle details.
Can these declarations have a common way of resolution ?
If yes, maybe this is too high-level and it results in yet
another not-so-formal-but-intuitive description.
If no, should we consider each case separately ? How many are they ?
How complicated will the DIP be ?

And it's not clear whether I will have the time to do this.

Tell me what you think.

- Stefanos
September 11
On 11.09.19 20:29, Stefanos Baziotis wrote:
> So, the alternative:
> My first thought is being more high level.
> That is, currently the DIP is restricted to alias declarations,
> while we can have the same exact semantic entity using a
> different type of declaration. This has a lot of subtle details.
> Can these declarations have a common way of resolution ?

The longhand is a common way. If you base your DIP on the longhand only, then the shorthand follows automatically, because it's defined to do whatever the longhand does.

I.e., if your DIP says that this works:

    template A(T) { alias A = S!T; } /* longhand */
    struct S(T) { }
    void f(T)(A!T arg) { }
    void main() { f(S!int()); }

Then it follows from the existing spec that it also works when A is declared in shorthand style:

    alias A(T) = S!T; /* shorthand */

The shorthand is defined to be equivalent to the longhand, and the longhand works, so the shorthand also works. You don't even have to mention it in the DIP. It's already in the spec.

By the way, the same shorthand/longhand thing applies to function templates. The DIP currently only uses the shorthand, but it should also work with the longhand (and I'd just assume that it does as long as the DIP doesn't explicitly say otherwise).

> If yes, maybe this is too high-level and it results in yet
> another not-so-formal-but-intuitive description.
> If no, should we consider each case separately ? How many are they ?
> How complicated will the DIP be ?

I feel like working on the (concrete) syntax level is too low-level.

I think it's obvious that the new feature should be applied after lexing and parsing. You don't want to write your DIP in terms of characters or keywords.

To me, it also seems obvious that the new feature should be applied after shorthand and longhand syntaxes have been consolidated. I'd expect that the parser already does this, but I'm not sure.

Beyond that, I'm not knowledgeable enough to say when it should happen. If the shorthand/longhand consolidation is not done by the parser, and not in some very early semantics phase either, then that might make things complicated.

> And it's not clear whether I will have the time to do this.

That's perfectly understandable. No one (in their right mind) is going to blame you, if you don't manage to push this all the way.

It's a hard problem. The oldest Bugzilla issue for it is over a decade old, with a dozen or so duplicates. Fixing/implementing that kind of issue isn't usually a walk in the park, or someone would already have done it.
1 2 3 4