www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - alias parameters and basic types

reply Lodovico Giaretta <lodovico giaretart.net> writes:
Hi,

I know this has been discussed before (like, before I started 
using D on a daily basis and hanging around in the forums), but...

Is there a reason why alias parameters do not accept basic types? 
Will this be changed somewhere in the future, as many asked for 
it? It is very surprising the first time it doesn't work and you 
are forced to add overloads...

Thank you for your answers.

Some quick links:
https://issues.dlang.org/show_bug.cgi?id=1100
https://issues.dlang.org/show_bug.cgi?id=3116
https://issues.dlang.org/show_bug.cgi?id=4639
https://issues.dlang.org/show_bug.cgi?id=8491
https://issues.dlang.org/show_bug.cgi?id=9029
Jul 30 2016
parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Saturday, July 30, 2016 18:53:43 Lodovico Giaretta via Digitalmars-d wrote:
 Hi,

 I know this has been discussed before (like, before I started
 using D on a daily basis and hanging around in the forums), but...

 Is there a reason why alias parameters do not accept basic types?
 Will this be changed somewhere in the future, as many asked for
 it? It is very surprising the first time it doesn't work and you
 are forced to add overloads...

 Thank you for your answers.

 Some quick links:
 https://issues.dlang.org/show_bug.cgi?id=1100
 https://issues.dlang.org/show_bug.cgi?id=3116
 https://issues.dlang.org/show_bug.cgi?id=4639
 https://issues.dlang.org/show_bug.cgi?id=8491
 https://issues.dlang.org/show_bug.cgi?id=9029
I think that Walter's answer in those bug reports is pretty clear. An alias parameter aliases a symbol. Basic types are keywords, not symbols, so they can't be passed as an argument to an alias parameter. And I confess that I don't know why you'd even want to. If you're looking to pass a type, then just don't use an alias parameter. A normal template parameter will do just fine. The only reason that I see that makes the current behavior a bit odd is the fact that other kinds of aliases do work with types. So, it's arguably inconsistent to not have alias parameters accept types, but given what alias parameters are intended for and that they're completely unnecessary for passing types, I don't really see a problem with the current behavior. In any case, glancing through those bugs, it's quite clear that the behavior is intentional what the reasoning is. - Jonathan M Davis
Jul 30 2016
next sibling parent reply Lodovico Giaretta <lodovico giaretart.net> writes:
On Saturday, 30 July 2016 at 19:21:27 UTC, Jonathan M Davis wrote:
 I think that Walter's answer in those bug reports is pretty 
 clear.
Thank you for your answer. I asked because I also found this[1], so I hoped it was going to change. [1] http://forum.dlang.org/post/lnaidcyffgqkvekawsmq forum.dlang.org
 An alias parameter aliases a symbol. Basic types are keywords, 
 not symbols, so they can't be passed as an argument to an alias 
 parameter.
If I define `alias Int = int`, then `Int` is a symbol, not a keyword. Yet it does not work, so the alias template does not prohibit keywords, it prohibits basic types, even when named without using a keyword.
 And I confess that I don't know why you'd even want to. If 
 you're looking to pass a type, then just don't use an alias 
 parameter. A normal template parameter will do just fine. The 
 only reason that I see that makes the current behavior a bit 
 odd is the fact that other kinds of aliases do work with types. 
 So, it's arguably inconsistent to not have alias parameters 
 accept types, but given what alias parameters are intended for 
 and that they're completely unnecessary for passing types, I 
 don't really see a problem with the current behavior.
I agree it is not a critical feature. Its main value, IMHO, is ortogonality and the principle of least-astonishment. My current use case is a template that (for convenience) accepts both types or variables, and in the case of variables applies `typeof` to get the type. It's only sugar, as I could require the user to apply `typeof` and only accept types in the template. With the current rules, I have to write two templates, one with alias that forwards to the other after applying `typeof`, while if alias could also accept every type, I would write just one template and use `static if` inside it.
 In any case, glancing through those bugs, it's quite clear that 
 the behavior is intentional what the reasoning is.
It is indeed intentional, I just don't see what this restriction buys. If it buys nothing (as I think it does), in terms of both compiler complexity and language complexity, it should go for the sake of consistency and ease of use (it's one less exception to remember). But I don't want to start a war over this, so please don't take this as an attack. It's just some considerations.
Jul 30 2016
parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Saturday, July 30, 2016 19:41:27 Lodovico Giaretta via Digitalmars-d wrote:
 On Saturday, 30 July 2016 at 19:21:27 UTC, Jonathan M Davis wrote:
 I think that Walter's answer in those bug reports is pretty
 clear.
Thank you for your answer. I asked because I also found this[1], so I hoped it was going to change. [1] http://forum.dlang.org/post/lnaidcyffgqkvekawsmq forum.dlang.org
Then maybe it'll change. I just know what was in the bug reports that you were listing. You seemed to be asking why the behavior was the way it was and then proceeded to ignore the links that you gave that explained exactly why.
 An alias parameter aliases a symbol. Basic types are keywords,
 not symbols, so they can't be passed as an argument to an alias
 parameter.
If I define `alias Int = int`, then `Int` is a symbol, not a keyword. Yet it does not work, so the alias template does not prohibit keywords, it prohibits basic types, even when named without using a keyword.
That's because aliases don't really exist. When an alias is declared, every instance of its used is effectively replaced textually. The compiler doesn't care about the alias beyond translating it into what it's aliased to. So, if you have alias Int = int; and you use Int somewhere, it's semantically identical to using int. You don't actually get a symbol called Int out of the deal. You just get to call int Int.
 And I confess that I don't know why you'd even want to. If
 you're looking to pass a type, then just don't use an alias
 parameter. A normal template parameter will do just fine. The
 only reason that I see that makes the current behavior a bit
 odd is the fact that other kinds of aliases do work with types.
 So, it's arguably inconsistent to not have alias parameters
 accept types, but given what alias parameters are intended for
 and that they're completely unnecessary for passing types, I
 don't really see a problem with the current behavior.
I agree it is not a critical feature. Its main value, IMHO, is ortogonality and the principle of least-astonishment. My current use case is a template that (for convenience) accepts both types or variables, and in the case of variables applies `typeof` to get the type. It's only sugar, as I could require the user to apply `typeof` and only accept types in the template. With the current rules, I have to write two templates, one with alias that forwards to the other after applying `typeof`, while if alias could also accept every type, I would write just one template and use `static if` inside it.
I confess that I've always thought that it's messy to have a template accept both types and objects, but there are folks who like to do that. But since I never do, I never hit any cases where it would matter.
 In any case, glancing through those bugs, it's quite clear that
 the behavior is intentional what the reasoning is.
It is indeed intentional, I just don't see what this restriction buys. If it buys nothing (as I think it does), in terms of both compiler complexity and language complexity, it should go for the sake of consistency and ease of use (it's one less exception to remember). But I don't want to start a war over this, so please don't take this as an attack. It's just some considerations.
The one that needs to be convinced is Walter. Personally, I really don't care. I don't really see any value in it, but I'm not against it. I was just telling you what Walter had said, since you seemed to be posting links without reading them. But if David did indeed convince Walter (as the link above implies), then presumably it'll change at some point. It wouldn't surprise me though if Walter has forgotten about it if it hasn't happened by now. - Jonathan M Davis
Jul 30 2016
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 30.07.2016 22:58, Jonathan M Davis via Digitalmars-d wrote:
 The one that needs to be convinced is Walter.
IIRC he said at DConf that it should be fixed.
Jul 30 2016
parent reply deadalnix <deadalnix gmail.com> writes:
On Saturday, 30 July 2016 at 21:21:30 UTC, Timon Gehr wrote:
 On 30.07.2016 22:58, Jonathan M Davis via Digitalmars-d wrote:
 The one that needs to be convinced is Walter.
IIRC he said at DConf that it should be fixed.
We did a tour of DConf 2015 with David Nadlinger and everybody was super confused by this behavior. Pretty much everybody but Walter, David and myself could tell you how this behaves. Even Andrei got it wrong. I take that, as you weren't there at the 2016 event, it was reiterated in 2016.
Jul 30 2016
parent reply Steven Schveighoffer <schveiguy yahoo.com> writes:
On 7/30/16 5:26 PM, deadalnix wrote:
 On Saturday, 30 July 2016 at 21:21:30 UTC, Timon Gehr wrote:
 On 30.07.2016 22:58, Jonathan M Davis via Digitalmars-d wrote:
 The one that needs to be convinced is Walter.
IIRC he said at DConf that it should be fixed.
We did a tour of DConf 2015 with David Nadlinger and everybody was super confused by this behavior. Pretty much everybody but Walter, David and myself could tell you how this behaves. Even Andrei got it wrong.
Walter got it wrong too, I saw when David asked him. That's when he said it should be fixed. The question was, if I alias Int = int, then Int is a symbol. If I pass it as an alias parameter, should it work?
 I take that, as you weren't there at the 2016 event, it was reiterated
 in 2016.
Timon was at dconf 2016. I don't recall it being discussed either, but maybe in a small discussion? I think we should fix this. The fact that you can alias int directly, but it can't be accepted as an alias parameter makes no sense. It's completely doable, and the philosophical argument is destroyed by the example. -Steve
Jul 31 2016
parent deadalnix <deadalnix gmail.com> writes:
On Sunday, 31 July 2016 at 11:50:35 UTC, Steven Schveighoffer 
wrote:
 On 7/30/16 5:26 PM, deadalnix wrote:
 I take that, as you weren't there at the 2016 event, it was 
 reiterated
 in 2016.
Timon was at dconf 2016. I don't recall it being discussed either, but maybe in a small discussion?
I meant he was not there in 2015, sorry for the confusion.
Jul 31 2016
prev sibling next sibling parent ag0aep6g <anonymous example.com> writes:
On 07/30/2016 09:21 PM, Jonathan M Davis via Digitalmars-d wrote:
 I think that Walter's answer in those bug reports is pretty clear. An alias
 parameter aliases a symbol. Basic types are keywords, not symbols, so they
 can't be passed as an argument to an alias parameter.
As far as I see, he just says that it works as intended. But he doesn't give a rationale as for why it's intended to work like that. What's gained by rejecting basic types in alias parameters? It's surprising behavior for seemingly no good reason.
 And I confess that I don't know why you'd even want to.
Phobos could make good use of it. For example, many isFoo template in std.traits would become a bit nicer. This kind of workaround is all over the place: template isCallable(T...) if (T.length == 1) { /* use T[0] */ } With a "fixed" alias parameter, that would be: template isCallable(alias T) { /* use T */ }
Jul 30 2016
prev sibling parent deadalnix <deadalnix gmail.com> writes:
On Saturday, 30 July 2016 at 19:21:27 UTC, Jonathan M Davis wrote:
 I think that Walter's answer in those bug reports is pretty 
 clear. An alias parameter aliases a symbol. Basic types are 
 keywords, not symbols, so they can't be passed as an argument 
 to an alias parameter.
alias bind to builtin types. There is no reason alias parameter shouldn't. Having alias bind to basic type is some cases and not in others is just plain retarded. You can always look at each example individually and conclude that's fine. And, in fact, that's fine, when each of these is taken individually. But when you look at the whole, it just doesn't add up.
 And I confess that I don't know why you'd even want to.
Unless that it is a polite way to say "it's useless", this show more lack of imagination than an actual problem with binding builtins. Anyway, the use case is not super common, but it happened to me in the past, and resulted in great puzzling. Especially since, alias parameter freaking bind to values (which are not symbols either) and alias declaration do not. The whole thing is completely messed up.
Jul 30 2016