digitalmars.D - Types: The Next Generation (Was: Why is phobos so wack?)
- Nick Sabalausky (Abscissa) (42/51) Jul 09 2017 Related to this, I've been giving some thought lately to a little bit of...
- Meta (6/48) Jul 09 2017 I'm sorry if I misunderstood what you're proposing, but isn't
- Nick Sabalausky (3/7) Jul 09 2017 Shit, I hope not :/ I gave up following C++ developments 15 years
- Meta (8/17) Jul 09 2017 There's a couple posts he's made here but a lot of it's spread
- Nick Sabalausky (5/12) Jul 09 2017 Ah, I guess it is very similar after all, except it'd be based on
- Nick Sabalausky (Abscissa) (119/123) Jul 09 2017 Ha ha, I still feel more than a little silly for pitching what amounts
- Jacob Carlborg (6/158) Jul 10 2017 Something like this has been proposed several times before, but Andrei
- Nick Sabalausky (Abscissa) (26/31) Jul 10 2017 Well, the nice thing about this approach (basing a concept-ish system
- Jacob Carlborg (5/30) Jul 10 2017 Here I disagree. I think that D should have something like this.
- Nick Sabalausky (Abscissa) (11/23) Jul 10 2017 Oh, I didn't mean to imply that I wouldn't love to have it in D
- Nick Sabalausky (Abscissa) (5/16) Jul 10 2017 I especially wanted to avoid any the "How dare you even consider
- Jacob Carlborg (4/21) Jul 10 2017 Fair enough.
- bpr (7/11) Jul 10 2017 You've seen this, right?
- Nick Sabalausky (Abscissa) (26/35) Jul 10 2017 Yea, I've seen that. It'd be a nice improvent for D and I'm definitely
- bpr (7/11) Jul 10 2017 You've seen this, right?
- bpr (7/11) Jul 10 2017 You've seen this, right?
- bpr (3/15) Jul 10 2017 Sorry about the repeat posting, I could observe the software
- Martin Nowak (8/9) Jul 10 2017 Looks like concepts.
- Nick Sabalausky (Abscissa) (5/17) Jul 10 2017 Sounds nice.
- bpr (8/10) Jul 10 2017 You've seen this, right?
- Marco Leise (8/11) Jul 10 2017 Am Sun, 9 Jul 2017 16:22:16 -0400
- Mark (35/54) Jul 15 2017 This reminds me of the "RAII vs. scope" arguments that came up on
On 07/09/2017 09:26 AM, Adam D. Ruppe wrote:On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote:Related to this, I've been giving some thought lately to a little bit of re-designing types themselves. Specifically, type creation tools that go beyond what structs and classes give us and allow better handling D-style generics. It's all very incomplete right now, but basically here's the gist: Awesome as D's generics, ranges, etc all are, they do make two things far more convoluted than when using basic straightforward types: Function declarations, and error messages when things don't match. So, why not encapsulate much of that stuff we merely *describe* in signatures for generic functions into genuine honest-to-goodness types? There would be user-defined symbols, such as "InputRange" or "SomeString", or "RandomAccessRange!SomeString", which the type system sees as actual types. And naturally there would be some mechanism for actually defining those types. Then, defining a function like this: SomeString fizzbar(RandomAccessRange!SomeNumeric r) {...} ...would automatically imply to the compiler all (or at least a lot of) the pluming we usually clutter the function declaration with: Defining the templated types and calling the appropriate if(isBlahBlah) constraints. About the only things remaining would be additional constraints not already defined by the next-gen types, and restrictions on how the parameters relate to each other. Even better, having all that encapsulated into genuine types should make it easier for the compiler to provide better error messages. Thought could also be put into additional type-creation tools that cater specifically to common things (again, such as ranges) to help streamline the process of creating them (ranges are awesome, but let's face it, defining them can be a bother - there's gotta be some way to make it simpler. For example, input ranges especially would GREATLY benefit from And of course, Nemerle-like (ML/Haskell-inspired) algebraics would be a wonderful capability to encorporate as well. Another area to explore would be merging the two sets of parameter lists (the compile-time list and the run-time list) into one list. Certain types would be known to imply "compile-time". A keyword/attr could be used to force compile-time or runtime. And for other params, a sufficiently-smart compiler could conceivably even choose "runtime" vs "compile-time" (or even, "it varies") based on optimization priorities. It would simplify the syntax for users, and help get around fear of templates. Obviously this is all very incomplete, but it's an idea I think is rather interesting.return str.join(" "); [...] Error: template std.array.join cannot deduce function from argument types !()(string, string) [...] simply trying to join a string[] with a separator.The error message sucks, but you clearly have a string when you meant string[].
Jul 09 2017
On Sunday, 9 July 2017 at 20:22:16 UTC, Nick Sabalausky (Abscissa) wrote:On 07/09/2017 09:26 AM, Adam D. Ruppe wrote:I'm sorry if I misunderstood what you're proposing, but isn't this exactly what C++ set out to do with concepts? If that's the case, I'd recommend you look up some of Andrei's refutation of concepts in favour of template guards and `static if`.On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote:argumentreturn str.join(" "); [...] Error: template std.array.join cannot deduce function fromyou meanttypes !()(string, string) [...] simply trying to join a string[] with a separator.The error message sucks, but you clearly have a string whenstring[].Related to this, I've been giving some thought lately to a little bit of re-designing types themselves. Specifically, type creation tools that go beyond what structs and classes give us and allow better handling D-style generics. It's all very incomplete right now, but basically here's the gist: Awesome as D's generics, ranges, etc all are, they do make two things far more convoluted than when using basic straightforward types: Function declarations, and error messages when things don't match. So, why not encapsulate much of that stuff we merely *describe* in signatures for generic functions into genuine honest-to-goodness types? There would be user-defined symbols, such as "InputRange" or "SomeString", or "RandomAccessRange!SomeString", which the type system sees as actual types. And naturally there would be some mechanism for actually defining those types. Then, defining a function like this: SomeString fizzbar(RandomAccessRange!SomeNumeric r) {...} ...would automatically imply to the compiler all (or at least a lot of) the pluming we usually clutter the function declaration with: Defining the templated types and calling the appropriate if(isBlahBlah) constraints. About the only things remaining would be additional constraints not already defined by the next-gen types, and restrictions on how the parameters relate to each other. Even better, having all that encapsulated into genuine types should make it easier for the compiler to provide better error messages.
Jul 09 2017
On Sunday, 9 July 2017 at 20:42:39 UTC, Meta wrote:I'm sorry if I misunderstood what you're proposing, but isn't this exactly what C++ set out to do with concepts? If that's the case, I'd recommend you look up some of Andrei's refutation of concepts in favour of template guards and `static if`.Shit, I hope not :/ I gave up following C++ developments 15 years ago. Happen to have a link handy to that refutation?
Jul 09 2017
On Sunday, 9 July 2017 at 21:59:04 UTC, Nick Sabalausky wrote:On Sunday, 9 July 2017 at 20:42:39 UTC, Meta wrote:There's a couple posts he's made here but a lot of it's spread out across various talks, articles (I think) as well as newsgroup posts. Here's what I found with a quick google: https://www.reddit.com/r/cpp/comments/4jqg5z/andrei_alexandrescu_on_c_concepts/ https://www.reddit.com/r/programming/comments/4jlkhv/accu_2016_keynote_by_andrei_alexandrescu/d391585/ And there's a ton of info on the internet about the C++ concepts proposal.I'm sorry if I misunderstood what you're proposing, but isn't this exactly what C++ set out to do with concepts? If that's the case, I'd recommend you look up some of Andrei's refutation of concepts in favour of template guards and `static if`.Shit, I hope not :/ I gave up following C++ developments 15 years ago. Happen to have a link handy to that refutation?
Jul 09 2017
On Sunday, 9 July 2017 at 22:02:51 UTC, Meta wrote:There's a couple posts he's made here but a lot of it's spread out across various talks, articles (I think) as well as newsgroup posts. Here's what I found with a quick google: https://www.reddit.com/r/cpp/comments/4jqg5z/andrei_alexandrescu_on_c_concepts/ https://www.reddit.com/r/programming/comments/4jlkhv/accu_2016_keynote_by_andrei_alexandrescu/d391585/ And there's a ton of info on the internet about the C++ concepts proposal.Ah, I guess it is very similar after all, except it'd be based on top of and coexist with all of D's design by introspection stuff (rather than exist without it as with C++), thus avoiding a lot of the downsides and getting best of both worlds.
Jul 09 2017
On 07/09/2017 09:21 PM, Nick Sabalausky wrote:Ah, I guess it is very similar after all, except it'd be based on top of and coexist with all of D's design by introspection stuff (rather than exist without it as with C++), thus avoiding a lot of the downsides and getting best of both worlds.Ha ha, I still feel more than a little silly for pitching what amounts to contracts as "an out-there idea I've been mulling over", but indulge in a little (partially-baked) taste to show this at least has some merit anyway. Hell, call it "concepts++" or "concepts, the D way" (note: I'm NOT pitching this as a suggestion for something D should do. Not saying D should or should'nt, just speaking purely in the realm of "langauge design brainstorming" here...Just because it's been on my mind and the "Why is phobos so wack?" thread brought some relevence) Behold! The power of combining constraints/design-by-introspection *with* concepts: Current declaration of std.array.join: --------------------------------------------------- ElementEncodingType!(ElementType!RoR)[] join(RoR, R)(RoR ror, scope R sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && isInputRange!R && is(Unqual!(ElementType!(ElementType!RoR)) == Unqual!(ElementType!R))); ElementEncodingType!(ElementType!RoR)[] join(RoR, E)(RoR ror, scope E sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && is(E : ElementType!(ElementType!RoR))); ElementEncodingType!(ElementType!RoR)[] join(RoR)(RoR ror) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR))); --------------------------------------------------- (ie, completely incomprehensible at-a-glance) Just one possibility of an entirely hypothetical D++ (assuming I'm even interpreting the D version correctly): --------------------------------------------------- // Note: This assumes the "ElementEncodingType vs ElementType" distinction // is nothing but a colossal mistake caused purely by the existance of // auto-decoding, which was (as an assumption this psuedo-code is predicated // upon) a complete clusterf*** of misdesign (Ie, *such* a huge stretch of // the imagination ;)), which in this hypothetical ideal langauge has // been killed dead with nuclear fire, and then beaten some more with // spiked crowbars, just to be sure. /++ Params: ror: an input range (or better) of input ranges (or better) of any type (shorthand for 'InputRange!InputRange!Type') sep: a separator that can be any input range ('InputRange!Type'). Returns: Shorthand for 'InputRange!Type': Ie, an input range (or better). Note: This is implicitly templated on typeof(ror) and typeof(sep). +/ InputRange join(InputRange!InputRange ror, InputRange sep) // Relationship constraints: if(UnqualTypeMatch!(ror, sep, return)) /++ Like above, but sep is 'Type' instead of 'InputRange!Type'. Since 'Type' is less specific than 'InputRange!Type', the prior overload is preferred. +/ InputRange join(InputRange!InputRange ror, Type sep) // Relationship constraints: if(unqualTypeMatch!(ror, InputRange!sep, return)) // No separator InputRange join(InputRange!InputRange ror) // Relationship constraints: if(unqualTypeMatch!(ror, return)) // Extra-special specialization: // Why multiple if() allowed? Because it makes the formatting less // of a mess, thus better readability. Good enough reason to me! InputRange join(InputRange!InputRange ror, Type sep) if(unqualTypeMatch!(ror, sep, return)) if(hasLength!typeof(sep)) { /+...take advantage of sep.length...+/ } // Note: Those constraints have further room for syntactical improvement. --------------------------------------------------- That example involves some additional things defined by the stdlib (*extremely* hypothetical syntax): --------------------------------------------------- concept InputRange(Element) { this() { // Current body of isInputRange here } // Most of isInputRange can *optionally* be replaced with: Element front(); void popFront(); bool empty(); } concept ForwardRange : InputRange // Builds upon InputRange { // Author can opt to do this (more powerful): this() { super.this(); typeof(this) x = this.save; } // Or this (more succinct): ForwardRange save(); } // *Anything*: A concrete (instatiable) type, or a templated // stand-in for a type (ie "T"), or an alias, or nothing at all. // Types *themselves* are first-class types! But implemented as // templates, rather than as runtime-OO. algebraic Any : Bottom; // An actual concrete type algrbraic Type : Any if(isType!this); // An actual concrete type? bool isType(Any any) {/+...introspection magic lies here...+/} // This is implicitly a template. bool unqualTypeMatch(InputRange!Any args...) { return args.map!(GetType).map!(Unqual).equal; } // If any is a static type, return any. // If any is a value, return typeof(any) // This is implicitly a template. Type GetType(Any any) { static if(typeof(any) == Type) return any; else return typeof(any); } --------------------------------------------------- Now, something like THAT is the language *I* would love to see. Obviously leaves a TON of details TBD, but one can dream ;)
Jul 09 2017
On 2017-07-10 07:54, Nick Sabalausky (Abscissa) wrote:On 07/09/2017 09:21 PM, Nick Sabalausky wrote: > > Ah, I guess it is very similar after all, except it'd be based on top of > and coexist with all of D's design by introspection stuff (rather than > exist without it as with C++), thus avoiding a lot of the downsides and > getting best of both worlds. Ha ha, I still feel more than a little silly for pitching what amounts to contracts as "an out-there idea I've been mulling over", but indulge in a little (partially-baked) taste to show this at least has some merit anyway. Hell, call it "concepts++" or "concepts, the D way" (note: I'm NOT pitching this as a suggestion for something D should do. Not saying D should or should'nt, just speaking purely in the realm of "langauge design brainstorming" here...Just because it's been on my mind and the "Why is phobos so wack?" thread brought some relevence) Behold! The power of combining constraints/design-by-introspection *with* concepts: Current declaration of std.array.join: --------------------------------------------------- ElementEncodingType!(ElementType!RoR)[] join(RoR, R)(RoR ror, scope R sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && isInputRange!R && is(Unqual!(ElementType!(ElementType!RoR)) == Unqual!(ElementType!R))); ElementEncodingType!(ElementType!RoR)[] join(RoR, E)(RoR ror, scope E sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && is(E : ElementType!(ElementType!RoR))); ElementEncodingType!(ElementType!RoR)[] join(RoR)(RoR ror) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR))); --------------------------------------------------- (ie, completely incomprehensible at-a-glance) Just one possibility of an entirely hypothetical D++ (assuming I'm even interpreting the D version correctly): --------------------------------------------------- // Note: This assumes the "ElementEncodingType vs ElementType" distinction // is nothing but a colossal mistake caused purely by the existance of // auto-decoding, which was (as an assumption this psuedo-code is predicated // upon) a complete clusterf*** of misdesign (Ie, *such* a huge stretch of // the imagination ;)), which in this hypothetical ideal langauge has // been killed dead with nuclear fire, and then beaten some more with // spiked crowbars, just to be sure. /++ Params: ror: an input range (or better) of input ranges (or better) of any type (shorthand for 'InputRange!InputRange!Type') sep: a separator that can be any input range ('InputRange!Type'). Returns: Shorthand for 'InputRange!Type': Ie, an input range (or better). Note: This is implicitly templated on typeof(ror) and typeof(sep). +/ InputRange join(InputRange!InputRange ror, InputRange sep) // Relationship constraints: if(UnqualTypeMatch!(ror, sep, return)) /++ Like above, but sep is 'Type' instead of 'InputRange!Type'. Since 'Type' is less specific than 'InputRange!Type', the prior overload is preferred. +/ InputRange join(InputRange!InputRange ror, Type sep) // Relationship constraints: if(unqualTypeMatch!(ror, InputRange!sep, return)) // No separator InputRange join(InputRange!InputRange ror) // Relationship constraints: if(unqualTypeMatch!(ror, return)) // Extra-special specialization: // Why multiple if() allowed? Because it makes the formatting less // of a mess, thus better readability. Good enough reason to me! InputRange join(InputRange!InputRange ror, Type sep) if(unqualTypeMatch!(ror, sep, return)) if(hasLength!typeof(sep)) { /+...take advantage of sep.length...+/ } // Note: Those constraints have further room for syntactical improvement. --------------------------------------------------- That example involves some additional things defined by the stdlib (*extremely* hypothetical syntax): --------------------------------------------------- concept InputRange(Element) { this() { // Current body of isInputRange here } // Most of isInputRange can *optionally* be replaced with: Element front(); void popFront(); bool empty(); } concept ForwardRange : InputRange // Builds upon InputRange { // Author can opt to do this (more powerful): this() { super.this(); typeof(this) x = this.save; } // Or this (more succinct): ForwardRange save(); } // *Anything*: A concrete (instatiable) type, or a templated // stand-in for a type (ie "T"), or an alias, or nothing at all. // Types *themselves* are first-class types! But implemented as // templates, rather than as runtime-OO. algebraic Any : Bottom; // An actual concrete type algrbraic Type : Any if(isType!this); // An actual concrete type? bool isType(Any any) {/+...introspection magic lies here...+/} // This is implicitly a template. bool unqualTypeMatch(InputRange!Any args...) { return args.map!(GetType).map!(Unqual).equal; } // If any is a static type, return any. // If any is a value, return typeof(any) // This is implicitly a template. Type GetType(Any any) { static if(typeof(any) == Type) return any; else return typeof(any); } --------------------------------------------------- Now, something like THAT is the language *I* would love to see. Obviously leaves a TON of details TBD, but one can dream ;)Something like this has been proposed several times before, but Andrei doesn't seem to like it. He think it's a failure that all the conditions need to have a name, or something like that. I prefer your approach. -- /Jacob Carlborg
Jul 10 2017
On 07/10/2017 07:32 AM, Jacob Carlborg wrote:Something like this has been proposed several times before, but Andrei doesn't seem to like it. He think it's a failure that all the conditions need to have a name, or something like that. I prefer your approach.Well, the nice thing about this approach (basing a concept-ish system *on top* of existing D-style design-by-introspection, as opposed to a C++-like concepts with no D-like features to complement it), is that it *doesn't* require every little variation to be named. For example, in the same psuedo-code I posted, there's a function (the last join() overload) that takes an input range, but requires the input range to support hasLength. But notice that there is NO symbol created or used anywhere for InputRangeWithLength. IIUC, it sounds like C++ concepts would require such a symbol to be created. But with this, that would not be needed. One thing to keep in mind is that we're ALREADY creating names for many (not all, but definitely some) of these things. In effect, *every* time we have an 'isXXXXX' function (isSomeString, isForwardRange, etc), we're already creating a name for it. We already implicitly understand that just because it's unrealisting to name *everything* (which, indicentally, reminds me of old Java class hierarchies), doesn't mean we can't or shouldn't name some things. The other important thing I want to emplasize yet again (just in case, because I know from experience in the past it's exactly this kind of point that rarely gets noticed), I'm not proposing D do this. It'd be far too big a change and it's far too incomplete to even think of trying to push. (Even tiny straightforward improvements to D face dowwnright epic levels of resistance any more.) So again, it's just some brainstorming. Maybe D several decades from now, maybe some other language inspired by D, maybe nothing ever, whatever.
Jul 10 2017
On 2017-07-10 19:54, Nick Sabalausky (Abscissa) wrote:Well, the nice thing about this approach (basing a concept-ish system *on top* of existing D-style design-by-introspection, as opposed to a C++-like concepts with no D-like features to complement it), is that it *doesn't* require every little variation to be named. For example, in the same psuedo-code I posted, there's a function (the last join() overload) that takes an input range, but requires the input range to support hasLength. But notice that there is NO symbol created or used anywhere for InputRangeWithLength. IIUC, it sounds like C++ concepts would require such a symbol to be created. But with this, that would not be needed. One thing to keep in mind is that we're ALREADY creating names for many (not all, but definitely some) of these things. In effect, *every* time we have an 'isXXXXX' function (isSomeString, isForwardRange, etc), we're already creating a name for it. We already implicitly understand that just because it's unrealisting to name *everything* (which, indicentally, reminds me of old Java class hierarchies), doesn't mean we can't or shouldn't name some things.I agree, it's not me that need convincing :)The other important thing I want to emplasize yet again (just in case, because I know from experience in the past it's exactly this kind of point that rarely gets noticed), I'm not proposing D do this. It'd be far too big a change and it's far too incomplete to even think of trying to push. (Even tiny straightforward improvements to D face dowwnright epic levels of resistance any more.) So again, it's just some brainstorming. Maybe D several decades from now, maybe some other language inspired by D, maybe nothing ever, whatever.Here I disagree. I think that D should have something like this. -- /Jacob Carlborg
Jul 10 2017
On 07/10/2017 02:55 PM, Jacob Carlborg wrote:On 2017-07-10 19:54, Nick Sabalausky (Abscissa) wrote:Oh, I didn't mean to imply that I wouldn't love to have it in D (assuming it was all well-fleshed out and didn't have big problems). I just wanted to be crystal clear that I'm merely discussing a langauge design idea here rather than coming in saying "Hey, you people should all like this idea and go implement it put it into D!!!" It's easy for things to get taken that way here, and can result in knee-jerk reactions and otherwise derailing of what's really only intended as a theoretical academic discussion. If something *were* to come of it, and it worked great, and everybody was happy, then fantastic. That's just not what I'm bringing it up for, that's all.The other important thing I want to emplasize yet again (just in case, because I know from experience in the past it's exactly this kind of point that rarely gets noticed), I'm not proposing D do this. It'd be far too big a change and it's far too incomplete to even think of trying to push. (Even tiny straightforward improvements to D face dowwnright epic levels of resistance any more.) So again, it's just some brainstorming. Maybe D several decades from now, maybe some other language inspired by D, maybe nothing ever, whatever.Here I disagree. I think that D should have something like this.
Jul 10 2017
On 07/10/2017 04:14 PM, Nick Sabalausky (Abscissa) wrote:Oh, I didn't mean to imply that I wouldn't love to have it in D (assuming it was all well-fleshed out and didn't have big problems). I just wanted to be crystal clear that I'm merely discussing a langauge design idea here rather than coming in saying "Hey, you people should all like this idea and go implement it put it into D!!!" It's easy for things to get taken that way here, and can result in knee-jerk reactions and otherwise derailing of what's really only intended as a theoretical academic discussion. If something *were* to come of it, and it worked great, and everybody was happy, then fantastic. That's just not what I'm bringing it up for, that's all.I especially wanted to avoid any the "How dare you even consider speaking of something without fully implementing it first!" that tends to be common here. (Speaking of, *that* sort of thing is far more unprofessional than the mere "bad words" some people are so terrified of).
Jul 10 2017
On 2017-07-10 22:19, Nick Sabalausky (Abscissa) wrote:On 07/10/2017 04:14 PM, Nick Sabalausky (Abscissa) wrote:Fair enough. -- /Jacob CarlborgOh, I didn't mean to imply that I wouldn't love to have it in D (assuming it was all well-fleshed out and didn't have big problems). I just wanted to be crystal clear that I'm merely discussing a langauge design idea here rather than coming in saying "Hey, you people should all like this idea and go implement it put it into D!!!" It's easy for things to get taken that way here, and can result in knee-jerk reactions and otherwise derailing of what's really only intended as a theoretical academic discussion. If something *were* to come of it, and it worked great, and everybody was happy, then fantastic. That's just not what I'm bringing it up for, that's all.I especially wanted to avoid any the "How dare you even consider speaking of something without fully implementing it first!" that tends to be common here. (Speaking of, *that* sort of thing is far more unprofessional than the mere "bad words" some people are so terrified of).
Jul 10 2017
On Monday, 10 July 2017 at 01:21:08 UTC, Nick Sabalausky wrote:Ah, I guess it is very similar after all, except it'd be based on top of and coexist with all of D's design by introspection stuff (rather than exist without it as with C++), thus avoiding a lot of the downsides and getting best of both worlds.You've seen this, right? https://wiki.dlang.org/User:9rnsr/DIP:_Template_Parameter_Constraint A small step in one such direction, influenced by C++ concepts. That proto-DIP also raises a question I always had about why D doesn't allow chained template instantiation, but that's another DIP for another time.
Jul 10 2017
On 07/10/2017 11:58 AM, bpr wrote:You've seen this, right? https://wiki.dlang.org/User:9rnsr/DIP:_Template_Parameter_Constraint A small step in one such direction, influenced by C++ concepts. That proto-DIP also raises a question I always had about why D doesn't allow chained template instantiation, but that's another DIP for another time.Yea, I've seen that. It'd be a nice improvent for D and I'm definitely in favor of it. It doesn't especially excite me though just because it's a small incremental change and creates further syntactical differences between handling runtime-oriented symbols and compile-time-oriented symbols. Ie, I'd prefer "InputRange r" over "T r if InputRange" because it's vastly simpler and more consistent with non-templated variable declarations. But in a practical sense, that's be a much more major and difficult to retrofit that onto D, so the DIP sounds like an appropriate (if unexciting) direction for D to take. But what I find much more interesting than that DIP (again, from a purely academic standpoint) is taking all of these abilities and finding a way simplify them, while retaining all of their power, and create more overall consistency[1]. (That was *exactly* one of my big original draws to D in the first place - it took C++, then cleaned it all up and enhanced it. I have interest in brainstorming the same for D. I think there's been enough practical experience using D at this point for more streamlined designs to now be possible.) [1] Heck, on the consistency front, it even bugs the hell out of me when people do "foo()" to call/define a function, but then deliberately stick with "if ()"-style instead for keywords. Both are "identifier followed by parens", but whether or not a space is added between is *different* depending on whether the identifier is a symbol or a keyword. Unnecessary inconsistency. Maybe it's all the puzzle games I've played over my lifetime, but...want...to...simplify... ;)
Jul 10 2017
On Monday, 10 July 2017 at 01:21:08 UTC, Nick Sabalausky wrote:Ah, I guess it is very similar after all, except it'd be based on top of and coexist with all of D's design by introspection stuff (rather than exist without it as with C++), thus avoiding a lot of the downsides and getting best of both worlds.You've seen this, right? https://wiki.dlang.org/User:9rnsr/DIP:_Template_Parameter_Constraint A small step in one such direction, influenced by C++ concepts. That proto-DIP also raises a question I always had about why D doesn't allow chained template instantiation, but that's another DIP for another time.
Jul 10 2017
On Monday, 10 July 2017 at 01:21:08 UTC, Nick Sabalausky wrote:Ah, I guess it is very similar after all, except it'd be based on top of and coexist with all of D's design by introspection stuff (rather than exist without it as with C++), thus avoiding a lot of the downsides and getting best of both worlds.You've seen this, right? https://wiki.dlang.org/User:9rnsr/DIP:_Template_Parameter_Constraint A small step in one such direction, influenced by C++ concepts. That proto-DIP also raises a question I always had about why D doesn't allow chained template instantiation, but that's another DIP for another time.
Jul 10 2017
On Monday, 10 July 2017 at 16:16:40 UTC, bpr wrote:On Monday, 10 July 2017 at 01:21:08 UTC, Nick Sabalausky wrote:Sorry about the repeat posting, I could observe the software hiccuping on my browser...Ah, I guess it is very similar after all, except it'd be based on top of and coexist with all of D's design by introspection stuff (rather than exist without it as with C++), thus avoiding a lot of the downsides and getting best of both worlds.You've seen this, right? https://wiki.dlang.org/User:9rnsr/DIP:_Template_Parameter_Constraint A small step in one such direction, influenced by C++ concepts. That proto-DIP also raises a question I always had about why D doesn't allow chained template instantiation, but that's another DIP for another time.
Jul 10 2017
On Sunday, 9 July 2017 at 20:22:16 UTC, Nick Sabalausky (Abscissa) wrote:SomeString fizzbar(RandomAccessRange!SomeNumeric r) {...}Looks like concepts. We've settled on leveraging the already useful template constraints (at best in CNF [¹]) for better error messages. It's on the Agenda for later this year [²]. [¹]: https://github.com/dlang/phobos/pull/5461 [²]: https://wiki.dlang.org/Vision/2017H2_draft
Jul 10 2017
On 07/10/2017 09:16 AM, Martin Nowak wrote:On Sunday, 9 July 2017 at 20:22:16 UTC, Nick Sabalausky (Abscissa) wrote:Sounds nice. But I'm getting the distinct impression people are missing that I never actually proposed that D itself should do this. It's just academic brainstorming.SomeString fizzbar(RandomAccessRange!SomeNumeric r) {...}Looks like concepts. We've settled on leveraging the already useful template constraints (at best in CNF [¹]) for better error messages. It's on the Agenda for later this year [²]. [¹]: https://github.com/dlang/phobos/pull/5461 [²]: https://wiki.dlang.org/Vision/2017H2_draft
Jul 10 2017
On Sunday, 9 July 2017 at 20:22:16 UTC, Nick Sabalausky (Abscissa) wrote:Obviously this is all very incomplete, but it's an idea I think is rather interesting.You've seen this, right? https://wiki.dlang.org/User:9rnsr/DIP:_Template_Parameter_Constraint A small step in one such direction, influenced by C++ concepts. That proto-DIP also raises a question I always had about why D doesn't allow chained template instantiation, but that's another DIP for another time.
Jul 10 2017
Am Sun, 9 Jul 2017 16:22:16 -0400 schrieb "Nick Sabalausky (Abscissa)" <SeeWebsiteToContactMe semitwist.com>:[=E2=80=A6] a sufficiently-smart compiler could conceivably even choose "runtime" vs "compile-time" (or even, "it varies") based on optimization priorities.GCC already does this, i.e. find runtime arguments of constant value and generate a second instance of the function with that argument optimized out. --=20 Marco
Jul 10 2017
On Sunday, 9 July 2017 at 20:22:16 UTC, Nick Sabalausky (Abscissa) wrote:So, why not encapsulate much of that stuff we merely *describe* in signatures for generic functions into genuine honest-to-goodness types? There would be user-defined symbols, such as "InputRange" or "SomeString", or "RandomAccessRange!SomeString", which the type system sees as actual types. And naturally there would be some mechanism for actually defining those types. Then, defining a function like this: SomeString fizzbar(RandomAccessRange!SomeNumeric r) {...} ...would automatically imply to the compiler all (or at least a lot of) the pluming we usually clutter the function declaration with: Defining the templated types and calling the appropriate if(isBlahBlah) constraints. About the only things remaining would be additional constraints not already defined by the next-gen types, and restrictions on how the parameters relate to each other. Even better, having all that encapsulated into genuine types should make it easier for the compiler to provide better error messages.This reminds me of the "RAII vs. scope" arguments that came up on the forum a few times (see e.g. [1]). Many of the features in D (and other programming languages) can be theoretically (and practically, in some languages) implemented using the type system: resource management, template constraints, in/out contracts, function attributes (pure, nothrow, etc.), I/O streams, error handling, and probably others. This is sometimes profitable and sometimes not so much. If you're using some concept all over your code then encapsulating it in a type can reduce code duplication, improve readability and let you exploit various features of the type system to your benefit (e.g. subtyping: A RandomAccessRange being a subtype of InputRange, exception hierarchies, etc.). But if you're only using it once or twice then it's probably not worth the hassle. That is, the issue is scale. My general impression is that C++ tries (and often succeeds, pyrrhically) to do pretty much everything using the type system (specifically, classes): Resources, exceptions, iterators, interfaces, initialization lists, ... Almost everything is encapsulated in a type. Concepts (Lite) seem to me like a way to further enrich the type system, although concepts aren't exactly types. My opinion, in a nutshell, is that "ad-hocish" facilities like template constraints, the scope statement, contracts, etc. don't scale up, while more formal facilities like concepts, RAII, etc. don't scale *down*. As such, there is a need for both of them. With respect to the specific issue of ranges, I don't know Phobos well enough to have an opinion as to whether or not they should be made more formal (as types/concepts/...). The error messages should be more clear and precise, but I'm not convinced that an overhaul of the system is necessary to achieve that. [1] https://forum.dlang.org/post/tlsrpqvfeepcfbyfqzge forum.dlang.org
Jul 15 2017