Why is phobos so wack?
import string. ... return str.join(" "); gives Error: template std.array.join cannot deduce function from argument types !()(string, string), candidates are: \..\..\src\phobos\std\array.d(1591):std.array.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))) \..\..\src\phobos\std\array.d(1668):std.array.join(RoR, E)(RoR ror, scope E sep) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR)) && is(E : ElementType!(ElementType!RoR))) \..\..\src\phobos\std\array.d(1754): std.array.join(RoR)(RoR ror) if (isInputRange!RoR && isInputRange!(Unqual!(ElementType!RoR))) simply trying to join a string[] with a separator. I tend to get these types of errors when doing simple things in D. Virtually every other programming language just works as expected. You can pretty much just jump in there and pretty much guess at the function name, the arguments, and it will work. In Phobos, seems like it follows an anti-pattern. You always end up having to look at documentation unless you are familiar enough with D and use it in a regular basis to remember its quirks and odd behavior. Seems that the same functions are defined differently in different modules and the modules not always the expected ones. (strip is another one that throws me for a loop. I always try trim first... that is what everyone else uses, yeah, it's just a name, but then why strip?) Phobos seems to be rather unorganized and not logically put together. Any hopes of this ever getting fixed or do I need to start putting together my own library?
Re: Why is phobos so wack?
import std.array; import std.stdio; void main() { string[] strs = ["abc", "def"]; writeln(strs.join(" ")); } Works fine?
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote: [...] Your example is incomplete but this literally works for me. import std.stdio; import std.string; void main() { string[] words = [ "hello", "world", "!" ]; writeln(words.join(" ")); } You probably passed a string instead of a string[]. Virtually every other programming language just works as expected. You can pretty much just jump in there and pretty much guess at the function name, the arguments, and it will work. In my experience this simply isn't true. Error messages could be worlds better but no language lets you use it for more than toy purposes without ever having to look at some form of documentation.
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote: 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[]. Even the one line of code you posted gives this away `str` is a singular name. modules not always the expected ones. (strip is another one that throws me for a loop. I always try trim first... that is what everyone else uses, yeah, it's just a name, but then why strip?) strip is used by Python and Ruby too... of the languages i know, it is about half a half. BTW if you are ever searching, try my website: http://dpldocs.info/trim
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote: import string. ... return str.join(" "); gives Error: template std.array.join cannot deduce function from argument types !()(string, string) Well there's your mistake? There is no function `join` that takes (string, string). Everything after that is more detail that may or may not be useful, but reading the error message carefully, in order, is generally good enough. That said, it would be nice if the errors were less daunting somehow.
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 13:26:31 UTC, Adam D. Ruppe wrote: strip is used by Python and Ruby too... of the languages i know, it is about half a half. BTW if you are ever searching, try my website: http://dpldocs.info/trim I find this part of D very annoying as well. D looks like a C language, with a standard library written by a PHP/Python developer. It's a shame for a language with so much potential to fall victim to such bad taste =x I suppose I'm biased, and PHP/Python have a fair following, but after a few years of PHP coding (part time as part of a larger project) I'm not sure I will ever make a full psychological recovery..
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 13:26:31 UTC, Adam D. Ruppe wrote: The error message sucks, but you clearly have a string when you meant string[]. To answer the part "why" about them sucking, is that they are generic. Were join() just a regular function taking two strings, or two interfaces which string would implement, the messages would be better. I my experience D compiler is excellent at error messages when you don't go generic. Of course, that does not help much because the standard library is templated, not object-oriented. Generics, and metaprogramming in general, is extremely hard to implement so that the error messages are even close to as good as elsewhere. No matter the language. Or rather, it can be made to give good messages, C# is a piece of proof for that. But that's also a reson why C# templates are so wimpy and ungeneral compared to C++ and D. About C++ from what I've heard, generic error messages there are not only much worse than others, they are much worse than even D template errors!
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 17:07:16 UTC, bitwise wrote: I suppose I'm biased, and PHP/Python have a fair following, but after a few years of PHP coding (part time as part of a larger project) I'm not sure I will ever make a full psychological recovery.. PHP actually is one of the languages that call this `trim` But I've never had the kind of problems with D's names that I have with PHP's assorted weirdness.
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 17:13:11 UTC, Dukc wrote: To answer the part "why" about them sucking, is that they are generic. Eh, that's not really why... this is just a crappy implementation. We can do a lot better with the library and a lot better with the compiler without losing any of the genericness. Were join() just a regular function taking two strings, or two interfaces which string would implement, the messages would be better. Better yes, but still actually a bit crappy. I have one step of an improvement in the works: https://github.com/dlang/dmd/pull/6806 Consider something similar to that for the constraints too. It could highlight that you passed a string instead of a "range of ranges" and you'd have a pretty good idea at a glance, even with the generic templates. About C++ from what I've heard, generic error messages there are not only much worse than others, they are much worse than even D template errors! Indeed.
Re: Why is phobos so wack?
On 07/09/2017 06:12 PM, Adam D. Ruppe wrote: On Sunday, 9 July 2017 at 17:07:16 UTC, bitwise wrote: I suppose I'm biased, and PHP/Python have a fair following, but after a few years of PHP coding (part time as part of a larger project) I'm not sure I will ever make a full psychological recovery.. PHP actually is one of the languages that call this `trim` But I've never had the kind of problems with D's names that I have with PHP's assorted weirdness. It's nowhere remotely as bad as PHP (frankly, nothing else is), but D's growth over the years *has* left Phobos with a bit of a..."temporal inconsistancy" issue. Some things have been ironed out a bit (like how there was a module or two that used to use very unix CLI'ish naming conventions instead of D-ish namings), but there's still more to be done. And more will continue to be needed, with (ex.) allocators getting more and more finalized.
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 17:13:11 UTC, Dukc wrote: About C++ from what I've heard, generic error messages there are not only much worse than others, they are much worse than even D template errors! Yeah. You don't want to try reading the GCC message for a std::cout error. It's like 80 lines of different template overloads of the '<<' operator.
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 14:22:45 UTC, John Colvin wrote: That said, it would be nice if the errors were less daunting somehow. Better template constraint errors are on our Agenda for later this year. https://wiki.dlang.org/Vision/2017H2_draft
Re: Why is phobos so wack?
On Sunday, 9 July 2017 at 22:20:02 UTC, Adam D. Ruppe wrote: Eh, that's not really why... this is just a crappy implementation. We can do a lot better with the library and a lot better with the compiler without losing any of the genericness. But the more powerful the generics are, the harder it is to make good messages, that's what I'm saying. And that compared to the power of our metaprogramming, the messages aren't that bad after all. But I agree D can, and I believe will, imporove there regardless.
Types: The Next Generation (Was: Why is phobos so wack?)
On 07/09/2017 09:26 AM, Adam D. Ruppe wrote: > On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote: >> 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[]. 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 being definable in the mannar of C# stackless coroutines). 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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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: > On Sunday, 9 July 2017 at 12:56:55 UTC, FoxyBrown wrote: >> 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[]. 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. 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`.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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?
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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: 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? 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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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: 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. Sorry about the repeat posting, I could observe the software hiccuping on my browser...
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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 'isX' 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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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... ;)
Re: Types: The Next Generation (Was: Why is phobos so wack?)
On 07/10/2017 09:16 AM, Martin Nowak wrote: 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 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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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 'isX' 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
Re: Types: The Next Generation (Was: Why is phobos so wack?)
On 07/10/2017 02:55 PM, Jacob Carlborg wrote: On 2017-07-10 19:54, Nick Sabalausky (Abscissa) wrote: 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. 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.
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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).
Re: Types: The Next Generation (Was: Why is phobos so wack?)
Am Sun, 9 Jul 2017 16:22:16 -0400 schrieb "Nick Sabalausky (Abscissa)" : > […] 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. -- Marco
Re: Types: The Next Generation (Was: Why is phobos so wack?)
On 2017-07-10 22:19, Nick Sabalausky (Abscissa) wrote: 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). Fair enough. -- /Jacob Carlborg
Re: Types: The Next Generation (Was: Why is phobos so wack?)
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/tlsrpqvfeepcfbyfq...@forum.dlang.org