Jump to page: 1 2
Thread overview
[DIP] Resolution of Alias Template Parameters in Function Templates
May 18, 2019
Stefanos Baziotis
May 18, 2019
jmh530
May 18, 2019
Stefanos Baziotis
May 20, 2019
jmh530
May 20, 2019
jmh530
May 20, 2019
Stefanos Baziotis
May 20, 2019
Stefanos Baziotis
May 20, 2019
jmh530
May 20, 2019
Stefanos Baziotis
May 20, 2019
jmh530
May 20, 2019
jmh530
May 20, 2019
Stefanos Baziotis
May 20, 2019
jmh530
May 20, 2019
Stefanos Baziotis
May 20, 2019
Nick Treleaven
May 20, 2019
Stefanos Baziotis
May 18, 2019
Here is a DIP that I've been working the last couple of days:
https://github.com/baziotis/DIPs/blob/master/DIPs/DIP1021.md

It is a proposal about how to handle alias templates when they appear
as parameters in function templates.
It was initially proposed by Ilya here: https://forum.dlang.org/post/kvcrsoqozrflxibgxtlo@forum.dlang.org

as a GSoC project and then again by Seb as part of the DataFrame project:
https://forum.dlang.org/post/jyzgzxqgaggltgifwnxx@forum.dlang.org

There are also a couple of Bugzilla reports, 2 of those referenced in the DIP.

I tried to make it as much of a scientific paper as possible, but note that
I don't have experience either in writing papers or DIPs.

The DIP references a PR with a 3-day prototype implementation. That was an initial
implementation that I was working before identifying all the corner cases of the feature.
And the corner cases make it such that probably a lot of time has to be spent
for this feature to be fully supported. I believe however that it might come in handy
as it handles a lot of the Slice cases, which are the primal motivation behind this.
This is not my main GSoC project so I won't have to work on that on the summer, but if anyone wants to work on it, please keep me posted.
The DIP also references an article that explains the problem in a more informal fashion style.
I'm planning to change this article to be more implementation-specific where I will analyze
the most important problems of implementing this fully.

Best,
Stefanos
May 18, 2019
On Saturday, 18 May 2019 at 12:32:13 UTC, Stefanos Baziotis wrote:
> Here is a DIP that I've been working the last couple of days:
> https://github.com/baziotis/DIPs/blob/master/DIPs/DIP1021.md
>
> It is a proposal about how to handle alias templates when they appear
> as parameters in function templates.
> It was initially proposed by Ilya here: https://forum.dlang.org/post/kvcrsoqozrflxibgxtlo@forum.dlang.org
>
> as a GSoC project and then again by Seb as part of the DataFrame project:
> https://forum.dlang.org/post/jyzgzxqgaggltgifwnxx@forum.dlang.org
>
> There are also a couple of Bugzilla reports, 2 of those referenced in the DIP.
>
> I tried to make it as much of a scientific paper as possible, but note that
> I don't have experience either in writing papers or DIPs.
>
> The DIP references a PR with a 3-day prototype implementation. That was an initial
> implementation that I was working before identifying all the corner cases of the feature.
> And the corner cases make it such that probably a lot of time has to be spent
> for this feature to be fully supported. I believe however that it might come in handy
> as it handles a lot of the Slice cases, which are the primal motivation behind this.
> This is not my main GSoC project so I won't have to work on that on the summer, but if anyone wants to work on it, please keep me posted.
> The DIP also references an article that explains the problem in a more informal fashion style.
> I'm planning to change this article to be more implementation-specific where I will analyze
> the most important problems of implementing this fully.
>
> Best,
> Stefanos

Thanks for working on this.

You might remove the line
"People seem to pay money for this feature to be implemented."
While people (like Ilya and me) are willing to pay for this, it's not really relevant to the technical issues.

Also, the forum has been discussing recently using static ifs within a function instead of function overloads. I think the same argument applies here. For instance, if switching to the commented code, then the writeln("here") will get skipped for writeln("there"). Correspondingly, I think it would be nice for the DIP to also discuss resolving is expressions as well.

struct Slice(T) {
}

struct StairsIterator(T, string direction) {
}

alias PackedUpperTriangularMatrix(T) = Slice!(StairsIterator!(T*, "-"));

auto foo(T)(T m)
{
    import std.stdio : writeln;

    static if (is(T : Slice!(StairsIterator!(U*, "-")), U)) {
    //static if (is(T : PackedUpperTriangularMatrix!U, U)) {
        writeln("here");
    } else static if (is(T : Slice!U, U)) {
        writeln("there");
    } else {
        static assert(0, "should not be here");
    }
}

void main()
{
    Slice!int x;
    PackedUpperTriangularMatrix!int y;
    foo(x);
    foo(y);

    import std.stdio : writeln;
    writeln(is(typeof(y) : PackedUpperTriangularMatrix!U, U)); //prints false
    writeln(is(typeof(y) : Slice!(StairsIterator!(U*, "-")), U)); //prints true
}
May 18, 2019
On Saturday, 18 May 2019 at 16:05:10 UTC, jmh530 wrote:
>
> Thanks for working on this.
>

Your welcome.

>
> You might remove the line
> "People seem to pay money for this feature to be implemented."
> While people (like Ilya and me) are willing to pay for this, it's not really relevant to the technical issues.
>

Good point, this is probably the least edited part of the code. It probably came from early draft versions. Removed.

> Also, the forum has been discussing recently using static ifs within a function instead of function overloads. I think the same argument applies here. For instance, if switching to the commented code, then the writeln("here") will get skipped for writeln("there"). Correspondingly, I think it would be nice for the DIP to also discuss resolving is expressions as well.
>

Thanks for the information, I was not aware. But, it's not really clear
what the behaviour should be. Look point 2. here [1]. What I understand
is that the general idea is to make aliases more identical to what they alias
rather than distinguishing them.

This DIP is a step towards that.

That seems to be the direction of the compiler source code as well.

On the other hand, the behaviour that you would expect in the examples distinguishes them.

In my opinion, I think that there should be a clear direction towards the one or the other.
But of course this is not necessarily what you, the community and / or the language
maintainers want. In that case, because it is a matter of opinion, it is not (fortunately) up to me to decide. We just need to listen to what most people want / care about
along with some rationale backing it up. :)

That is, in what cases they are different and in what they're not.
This could be as simple as "only in `is` case they are different" or way
more complicated.


[1] https://dlang.org/spec/declaration.html#alias


May 20, 2019
On Saturday, 18 May 2019 at 12:32:13 UTC, Stefanos Baziotis wrote:
| https://github.com/baziotis/DIPs/blob/master/DIPs/DIP1021.md

Assume you mean: https://github.com/baziotis/DIPs/blob/master/Drafts/1NNN-SB.md
May 20, 2019
On Saturday, 18 May 2019 at 16:52:45 UTC, Stefanos Baziotis wrote:
> [snip]
>
> Thanks for the information, I was not aware. But, it's not really clear
> what the behaviour should be. Look point 2. here [1]. What I understand
> is that the general idea is to make aliases more identical to what they alias
> rather than distinguishing them.
>
> This DIP is a step towards that.
>
> That seems to be the direction of the compiler source code as well.
>
> On the other hand, the behaviour that you would expect in the examples distinguishes them.
>
> In my opinion, I think that there should be a clear direction towards the one or the other.
> But of course this is not necessarily what you, the community and / or the language
> maintainers want. In that case, because it is a matter of opinion, it is not (fortunately) up to me to decide. We just need to listen to what most people want / care about
> along with some rationale backing it up. :)
>
> That is, in what cases they are different and in what they're not.
> This could be as simple as "only in `is` case they are different" or way
> more complicated.
>
>
> [1] https://dlang.org/spec/declaration.html#alias


Hmm, the link to the DIP isn't working for me now.


My rationale would be that, from a generic code perspective, it is very helpful if alias templates behave like aliases (including both is expressions and use in functions). There may be good reasons why that shouldn't or can't be the case, but I think the goal should be on allowing for the most generic code possible.

It may be useful to include in the DIP the cases where alias templates can and cannot be used like aliases...

May 20, 2019
On Monday, 20 May 2019 at 14:27:48 UTC, Nick Treleaven wrote:
> On Saturday, 18 May 2019 at 12:32:13 UTC, Stefanos Baziotis wrote:
> | https://github.com/baziotis/DIPs/blob/master/DIPs/DIP1021.md
>
> Assume you mean: https://github.com/baziotis/DIPs/blob/master/Drafts/1NNN-SB.md

Yes, thank you, I updated it just yesterday and forgot it.
May 20, 2019
On Monday, 20 May 2019 at 14:45:59 UTC, jmh530 wrote:
> [snip
>
> Hmm, the link to the DIP isn't working for me now.
>

Ah, found it again
https://github.com/baziotis/DIPs/blob/master/Drafts/1NNN-SB.md

I don't see that "Changing the parameter type might not be enough" caveat as being that big of an issue. I see the problem as coming from the alias
alias TemplateAlias(S, V) = TemplateType!(S);
There is no reason for V to be there. You could just as easily write
alias TemplateAlias(S, V = null) = TemplateType!(S);
However, the user may not be able to change TemplateAlias, in which case something like
alias TemplateAlias(S) = TemplateAlias!(S, typeof(null));
might be an acceptable solution I think.
May 20, 2019
On Monday, 20 May 2019 at 14:45:59 UTC, jmh530 wrote:
>
> Hmm, the link to the DIP isn't working for me now.
>

Yes, I updated it yesterday, please use this link: https://github.com/baziotis/DIPs/blob/master/Drafts/1NNN-SB.md

>
> My rationale would be that, from a generic code perspective, it is very helpful if alias templates behave like aliases (including both is expressions and use in functions). There may be good reasons why that shouldn't or can't be the case, but I think the goal should be on allowing for the most generic code possible.
>

I agree, but with the current proposal, they do behave like aliases in that,
there is no distinction between the true type and the alias.

Here is an example similar to yours above:

alias Num = int;

auto foo(T)(T m)
{
    import std.stdio : writeln;

    static if (is(T : int)) {
        writeln("here");
    } else static if (is(T : Num)) {
        writeln("there");
    } else {
        static assert(0, "should not be here");
    }
}

void main()
{
    Num x;
    int y;
    foo(x);
    foo(y);
}

Both of them go to "here". The `Num` one does not go to "there". That is, it can't
be distinguished whether we have an int because of an alias or because we
actually had an int. And that I understand that it is one of the important points
of aliases.

Of course, I may have missed / misunderstood something badly in all of that,
but I understand that distinguishing them (e.g. in your example above)
makes template aliases different than normal aliases.

May 20, 2019
On Monday, 20 May 2019 at 17:35:23 UTC, jmh530 wrote:
>
> I don't see that "Changing the parameter type might not be enough" caveat as being that big of an issue. I see the problem as coming from the alias
> alias TemplateAlias(S, V) = TemplateType!(S);


I agree with you, but there might be more to it than it meets the eye
because of course, it is accepted by the language currently.

Other than that, to end up that this is a problem of aliases is irrelevant to the DIP. It doesn't have to do with template functions or template aliases as parameters to template functions.

> There is no reason for V to be there. You could just as easily write
> alias TemplateAlias(S, V = null) = TemplateType!(S);

This still causes the drop of a template function template parameter.

> However, the user may not be able to change TemplateAlias, in which case something like
> alias TemplateAlias(S) = TemplateAlias!(S, typeof(null));
> might be an acceptable solution I think.

Yes, but that is how the user decides to solve it.
Again, concluding about what aliases are acceptable and what not is a separate
topic, which is of course important.
May 20, 2019
On Monday, 20 May 2019 at 17:36:35 UTC, Stefanos Baziotis wrote:
> [snip]
>
> Both of them go to "here". The `Num` one does not go to "there". That is, it can't
> be distinguished whether we have an int because of an alias or because we
> actually had an int. And that I understand that it is one of the important points
> of aliases.
>
> Of course, I may have missed / misunderstood something badly in all of that,
> but I understand that distinguishing them (e.g. in your example above)
> makes template aliases different than normal aliases.

Yes, that's what you would expect to happen with a normal alias.

If you change the alias to
alias Num(T) = T;
and the second is statement to
is(T : Num!U, U)
then it becomes equivalent to what I had done above. This fails for the same reason as discussed above.
« First   ‹ Prev
1 2