www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - My Meeting C++ Keynote video is now available

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
https://youtube.com/watch?v=tcyb1lpEHm0

If nothing else please watch the opening story, it's true and quite 
funny :o).

Now as to the talk, as you could imagine, it touches on another language 
as well...


Andrei
Jan 12
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/12/2019 7:51 AM, Andrei Alexandrescu wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0
Wonderful talk! The questions asked at the end were great, too.
Jan 12
prev sibling next sibling parent reply Bastiaan Veelo <Bastiaan Veelo.net> writes:
On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei Alexandrescu 
wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0

 If nothing else please watch the opening story, it's true and 
 quite funny :o).

 Now as to the talk, as you could imagine, it touches on another 
 language as well...


 Andrei
Top notch, as usual. Nice progression from “another language” through “the other language”, “d (other) language” to finally just “D language“ :-) Bastiaan.
Jan 12
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 1/12/19 7:21 PM, Bastiaan Veelo wrote:
 On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei Alexandrescu wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0

 If nothing else please watch the opening story, it's true and quite 
 funny :o).

 Now as to the talk, as you could imagine, it touches on another 
 language as well...


 Andrei
Top notch, as usual. Nice progression from “another language” through “the other language”, “d (other) language” to finally just “D language“ :-) Bastiaan.
Glad you noticed. It was deliberate.
Jan 12
prev sibling next sibling parent Jon Degenhardt <jond noreply.com> writes:
On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei Alexandrescu 
wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0

 If nothing else please watch the opening story, it's true and 
 quite funny :o).

 Now as to the talk, as you could imagine, it touches on another 
 language as well...


 Andrei
Very nice. I especially liked how design by introspection was contrasted with other approaches and how the constexpr discussion fit into the overall theme. --Jon
Jan 12
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/12/2019 7:51 AM, Andrei Alexandrescu wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0
One major takeaway is that the bugs/line are the same regardless of the language used. This means that languages that enable more expression in fewer lines of code result in fewer bugs for the same functionality. Another way to look at that is when refactoring code, look for ways of reducing the line count. It does not mean deleting comment lines, or putting several statements on one line. :-)
Jan 12
parent reply Tony <tonytdominguez aol.com> writes:
On Sunday, 13 January 2019 at 04:04:14 UTC, Walter Bright wrote:

 One major takeaway is that the bugs/line are the same 
 regardless of the language used. This means that languages that 
 enable more expression in fewer lines of code result in fewer 
 bugs for the same functionality.
Is the data to support this conclusion freely available on the web somewhere? My impression is that Python is considered the easiest language to use. If it has no more bugs per line than a statically typed program that seems to suggest that non-speed-critical work should be done in Python.
Jan 17
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jan 17, 2019 at 11:17:18AM +0000, Tony via Digitalmars-d-announce wrote:
 On Sunday, 13 January 2019 at 04:04:14 UTC, Walter Bright wrote:
 
 One major takeaway is that the bugs/line are the same regardless of
 the language used. This means that languages that enable more
 expression in fewer lines of code result in fewer bugs for the same
 functionality.
 
Is the data to support this conclusion freely available on the web somewhere? My impression is that Python is considered the easiest language to use. If it has no more bugs per line than a statically typed program that seems to suggest that non-speed-critical work should be done in Python.
No, if the number of bugs is truly proportional to the number of lines, then we should all ditch D and write APL instead. :-P T -- Leather is waterproof. Ever see a cow with an umbrella?
Jan 17
prev sibling next sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei Alexandrescu 
wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0
I especially like how design by introspection was contrasted with concepts and metaclasses, culminating in "We want to generate more smart code, not more boilerplate. We want to generate code that matters." Indeed. But what language features do we already have that are as "bo-riing" as concepts and metaclasses? What I wonder is, with design by introspection and the right mix of other language features (e.g. `alias`, `alias this`, mixins, etc...), what traditional language features can be removed from the compiler and delegated to library facilities? For example, https://theartofmachinery.com/2018/08/13/inheritance_and_polymorphism_2.html Because design by introspection allows us to "assemble programs atomically", perhaps high-level language features like classes and interfaces can become obsolete, and the language itself can be reduced simpler primitives that don't require the overhead of a runtime. Mike
Jan 13
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Monday, 14 January 2019 at 03:58:37 UTC, Mike Franklin wrote:
 What I wonder is, with design by introspection and the right 
 mix of other language features (e.g. `alias`, `alias this`, 
 mixins, etc...), what traditional language features can be 
 removed from the compiler and delegated to library facilities? 
 For example,  
 https://theartofmachinery.com/2018/08/13/inheritance_and_polymorphism_2.html

 Because design by introspection allows us to "assemble programs 
 atomically", perhaps high-level language features like classes 
 and interfaces can become obsolete, and the language itself can 
 be reduced simpler primitives that don't require the overhead 
 of a runtime.

 Mike
Scheme is probably the language that takes this idea of a minimal "core language" with powerful metaprogramming facilities the furthest, and the result is a fragmented ecosystem that makes writing portable, non-trivial programs close to impossible. (See "The Lisp Curse" [1].) When something like an object system is made part of the language (or at the very least, the standard library), it becomes a focal point [2] that the community can coordinate around. Due to the diverse, distributed nature of any programming-language community, trying to coordinate through explicit communication is not really a viable option, so having these kinds of focal points is very important if we want to be able to work together on anything. [1] http://winestockwebdesign.com/Essays/Lisp_Curse.html [2] https://en.wikipedia.org/wiki/Focal_point_(game_theory)
Jan 13
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/13/2019 9:31 PM, Paul Backus wrote:
 Scheme is probably the language that takes this idea of a minimal "core 
 language" with powerful metaprogramming facilities the furthest, and the
result 
 is a fragmented ecosystem that makes writing portable, non-trivial programs 
 close to impossible. (See "The Lisp Curse" [1].)
 
 When something like an object system is made part of the language (or at the 
 very least, the standard library), it becomes a focal point [2] that the 
 community can coordinate around. Due to the diverse, distributed nature of any 
 programming-language community, trying to coordinate through explicit 
 communication is not really a viable option, so having these kinds of focal 
 points is very important if we want to be able to work together on anything.
 
 [1] http://winestockwebdesign.com/Essays/Lisp_Curse.html
 [2] https://en.wikipedia.org/wiki/Focal_point_(game_theory)
Interesting cites, which provide a basis for why I've opposed AST macros, and why Ddoc and unittest are builtin (and a few other things). Also, before std::string came along in C++, everyone invented their own string class, and as a result, nobody could share code.
Jan 13
next sibling parent reply Martin Tschierschke <mt smartdolphin.de> writes:
On Monday, 14 January 2019 at 07:50:32 UTC, Walter Bright wrote:
 On 1/13/2019 9:31 PM, Paul Backus wrote:
 Scheme is probably the language that takes this idea of a 
 minimal "core language" with powerful metaprogramming 
 facilities the furthest, and the result is a fragmented 
 ecosystem that makes writing portable, non-trivial programs 
 close to impossible. (See "The Lisp Curse" [1].)
 
 When something like an object system is made part of the 
 language (or at the very least, the standard library), it 
 becomes a focal point [2] that the community can coordinate 
 around. Due to the diverse, distributed nature of any 
 programming-language community, trying to coordinate through 
 explicit communication is not really a viable option, so 
 having these kinds of focal points is very important if we 
 want to be able to work together on anything.
 
 [1] http://winestockwebdesign.com/Essays/Lisp_Curse.html
 [2] https://en.wikipedia.org/wiki/Focal_point_(game_theory)
Interesting cites, which provide a basis for why I've opposed AST macros, and why Ddoc and unittest are builtin (and a few other things). Also, before std::string came along in C++, everyone invented their own string class, and as a result, nobody could share code.
This is exactly the argument to get a database driver (mysql,postgres...) and probably a webserver in std. But to avoid getting std.lib to big, the D Foundation might adopt some third party libs as core libraries, so they get maintained within the D Foundation Git account to make them somehow official. We are now approaching the 1500 Dub package, and the ecosystem becomes more and more complex. (https://code.dlang.org/ 1482 packages: The search for mysql now returns 23 packages. Please tell me which to use for the back end, of your own vibe.d app. I give you 5 minutes...:-) Regards mt.
Jan 14
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/14/19 5:18 AM, Martin Tschierschke wrote:
 On Monday, 14 January 2019 at 07:50:32 UTC, Walter Bright wrote:
 On 1/13/2019 9:31 PM, Paul Backus wrote:
 Scheme is probably the language that takes this idea of a minimal 
 "core language" with powerful metaprogramming facilities the 
 furthest, and the result is a fragmented ecosystem that makes writing 
 portable, non-trivial programs close to impossible. (See "The Lisp 
 Curse" [1].)

 When something like an object system is made part of the language (or 
 at the very least, the standard library), it becomes a focal point 
 [2] that the community can coordinate around. Due to the diverse, 
 distributed nature of any programming-language community, trying to 
 coordinate through explicit communication is not really a viable 
 option, so having these kinds of focal points is very important if we 
 want to be able to work together on anything.

 [1] http://winestockwebdesign.com/Essays/Lisp_Curse.html
 [2] https://en.wikipedia.org/wiki/Focal_point_(game_theory)
Interesting cites, which provide a basis for why I've opposed AST macros, and why Ddoc and unittest are builtin (and a few other things). Also, before std::string came along in C++, everyone invented their own string class, and as a result, nobody could share code.
This is exactly the argument to get a database driver (mysql,postgres...) and probably a webserver in std.
I don't like the idea of it, because there are so many approaches. Even different approaches among one server protocol.
 
 But to avoid getting std.lib to big, the D Foundation might adopt some 
 third party libs as core libraries, so they get maintained within the D 
 Foundation Git account to make them somehow official.
 
 We are now approaching the 1500 Dub package, and the ecosystem becomes 
 more and more complex.
This is true, I searched yesterday for a decimal package that fits my use case (I'm getting decimal numbers as strings in a JSON library, with no limits as to what number of decimal places are supported). There were probably 4 or 5 that implement the general concept of a decimal type, but I was faced with a couple issues: 1. Is it maintained? Some of them are really old, some are old-ish, but could potentially be pretty stable 2. Does it have all the features I want? I am hesitant at this point to select something that has overflow problems, because I don't actually know how much would be too much. With one central package, I can be sure that 1 is answered, but then I don't actually have any choices for whether it works for me or not. If it doesn't implement the features I want (basically, I want completely arbitrary precision AND number of digits), then I still have to roll my own. Some packages are hard to solve every, if not most, requirements. Really that should be the defining feature of whether it goes into the standard library.
 (https://code.dlang.org/  1482 packages: The search for mysql now 
 returns 23 packages. Please tell me which to use for the back end, of 
 your own vibe.d app. I give you 5 minutes...:-)
 Regards mt.
That's a bad example :) The clear answer is mysql-native, which is what vibe.d recommends. -Steve
Jan 14
parent reply Jacob Carlborg <doob me.com> writes:
On 2019-01-14 15:42, Steven Schveighoffer wrote:

 That's a bad example :) The clear answer is mysql-native, which is what 
 vibe.d recommends.
Exactly, and I don't need five minutes for that. Five seconds is enough :) -- /Jacob Carlborg
Jan 14
parent reply Martin Tschierschke <mt smartdolphin.de> writes:
On Monday, 14 January 2019 at 18:52:02 UTC, Jacob Carlborg wrote:
 On 2019-01-14 15:42, Steven Schveighoffer wrote:

 That's a bad example :) The clear answer is mysql-native, 
 which is what vibe.d recommends.
Exactly, and I don't need five minutes for that. Five seconds is enough :)
Ok, bad example, but let's say you want ORM mapping, too and to have the ability to switch to Postgres later? So what would you recommend?
Jan 15
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/15/19 4:37 AM, Martin Tschierschke wrote:
 On Monday, 14 January 2019 at 18:52:02 UTC, Jacob Carlborg wrote:
 On 2019-01-14 15:42, Steven Schveighoffer wrote:

 That's a bad example :) The clear answer is mysql-native, which is 
 what vibe.d recommends.
Exactly, and I don't need five minutes for that. Five seconds is enough :)
Ok, bad example,  but let's say you want ORM mapping, too and to have the ability to switch to Postgres later? So what would you recommend?
I should have said that your point is mostly correct, just that this is a bad example :) I've looked for ORM on code.dlang.org, and never found one yet that I liked. So the answer would take infinite seconds to complete. But let's say we put ORM into Phobos. Certainly, it would get heavy use, but I would be likely to believe that it would not cover the problem space completely, and leave quite a bit to be desired. I think that there are some things that can go into the standard library and live there happily. There are other things that should be left to the community, even though they are essential, simply because locking into one implementation/API/idea is too restrictive. -Steve
Jan 16
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Wednesday, 16 January 2019 at 14:59:20 UTC, Steven 
Schveighoffer wrote:
 On 1/15/19 4:37 AM, Martin Tschierschke wrote:
 [...]
I should have said that your point is mostly correct, just that this is a bad example :) I've looked for ORM on code.dlang.org, and never found one yet that I liked. So the answer would take infinite seconds to complete. But let's say we put ORM into Phobos. Certainly, it would get heavy use, but I would be likely to believe that it would not cover the problem space completely, and leave quite a bit to be desired. I think that there are some things that can go into the standard library and live there happily. There are other things that should be left to the community, even though they are essential, simply because locking into one implementation/API/idea is too restrictive. -Steve
+1 I'm waiting, for example, for a revamp of IO, just to start... --- Paolo
Jan 16
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/16/19 10:06 AM, Paolo Invernizzi wrote:

 I'm waiting, for example, for a revamp of IO, just to start...
We're working on it... https://github.com/schveiguy/iopipe https://github.com/MartinNowak/io -Steve
Jan 16
parent reply Paolo Invernizzi <paolo.invernizzi gmail.com> writes:
On Wednesday, 16 January 2019 at 16:30:17 UTC, Steven 
Schveighoffer wrote:
 On 1/16/19 10:06 AM, Paolo Invernizzi wrote:

 I'm waiting, for example, for a revamp of IO, just to start...
We're working on it... https://github.com/schveiguy/iopipe https://github.com/MartinNowak/io -Steve
I was exactly referring to that two... they are great, and I've used both! Despite that, they seem stalled: any plan to go ahead in the medium term? Thanks for your work (and to Martin too) --- Paolo
Jan 16
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/16/19 11:43 AM, Paolo Invernizzi wrote:
 On Wednesday, 16 January 2019 at 16:30:17 UTC, Steven Schveighoffer wrote:
 On 1/16/19 10:06 AM, Paolo Invernizzi wrote:

 I'm waiting, for example, for a revamp of IO, just to start...
We're working on it... https://github.com/schveiguy/iopipe https://github.com/MartinNowak/io
I was exactly referring to that two... they are great, and I've used both! Despite that, they seem stalled: any plan to go ahead in the medium term?
Slowly... Sorry, it's not my day job to improve these :) But I am working currently on an http client using iopipe (https://github.com/schveiguy/httpiopipe) and improving/releasing the json parser that I wrote for my talk 2 years ago (https://github.com/schveiguy/jsoniopipe). Hint: I hope to have a working REST client soon. I also have a library that's stalled, but I have to pick it up again in order to deal with parsing using ranges (not yet published). I think in order to make this more palatable, though, we really do need to focus on the io base with some sort of async fiber-based driver.
 Thanks for your work (and to Martin too)
You're welcome! Thanks for the kind words. It's actually one of the more fun projects I have worked on. -Steve
Jan 16
prev sibling parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
On Monday, 14 January 2019 at 10:18:34 UTC, Martin Tschierschke 
wrote:
 This is exactly the argument to get a database driver 
 (mysql,postgres...) and probably a webserver in std.
Absolutely not! Please... IMHO, what needs to be in std are just APIs (modules, interfaces, declarations)... Leave the implementations elsewhere please. Standard library is already too large for my taste! What should be in std are just core stuff that is needed everywhere. However, the REFERENCE IMPLEMENTATIONS of these APIs could be, and in fact SHOULD be, in a set of higher-level implementation libraries that should be developed by the D Foundation, and available on the dlang.org for downloads. (part of some kind of Standard Library Suite)
Jan 16
parent JN <666total wp.pl> writes:
On Wednesday, 16 January 2019 at 11:35:15 UTC, Dejan Lekic wrote:
 On Monday, 14 January 2019 at 10:18:34 UTC, Martin Tschierschke 
 wrote:
 This is exactly the argument to get a database driver 
 (mysql,postgres...) and probably a webserver in std.
Absolutely not! Please... IMHO, what needs to be in std are just APIs (modules, interfaces, declarations)... Leave the implementations elsewhere please. Standard library is already too large for my taste! What should be in std are just core stuff that is needed everywhere.
Depends on what you consider core stuff. I don't think webserver should be a part of the standard library, but I think stuff like sockets, XML and JSON should. Serialization? Debatable. Database driver? Maybe not specific backends, but there could be a generic driver interface.
Jan 16
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2019-01-14 08:50, Walter Bright wrote:

 Interesting cites, which provide a basis for why I've opposed AST 
 macros, and why Ddoc and unittest are builtin (and a few other things).
But Ddoc has macros ;) -- /Jacob Carlborg
Jan 14
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/14/2019 10:49 AM, Jacob Carlborg wrote:
 But Ddoc has macros ;)
Indeed it does. But the macros cannot be used to create syntax, and there is no token concatenation. Macros cannot define other macros.
Jan 14
parent reply Jacob Carlborg <doob me.com> writes:
On 2019-01-14 23:52, Walter Bright wrote:
 On 1/14/2019 10:49 AM, Jacob Carlborg wrote:
 But Ddoc has macros ;)
Indeed it does. But the macros cannot be used to create syntax, and there is no token concatenation. Macros cannot define other macros.
The AST macros I've been talking about have never been able to create new syntax. -- /Jacob Carlborg
Jan 15
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/15/2019 1:10 AM, Jacob Carlborg wrote:
 The AST macros I've been talking about have never been able to create new
syntax.
Template expressions can't, either, but what they do is hijack the syntax for completely different purposes. The poor reader will be looking at code, and it will behave nothing like the syntax suggests.
Jan 15
parent reply Jacob Carlborg <doob me.com> writes:
On 2019-01-15 12:53, Walter Bright wrote:

 Template expressions can't, either, but what they do is hijack the 
 syntax for completely different purposes. The poor reader will be 
 looking at code, and it will behave nothing like the syntax suggests.
Ah, you mean like this: struct MyInt { private int value; MyInt add(MyInt other) { return MyInt(value - other.value); } } Perhaps we shouldn't support user defined types or functions either ;) -- /Jacob Carlborg
Jan 15
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/15/2019 10:39 AM, Jacob Carlborg wrote:
 Perhaps we shouldn't support user defined types or functions either ;)
You deliberately wrote that, and I'm confident you'd never try to pass that off as good work. With macros, however, programmers are convinced they are creating models of clarity. I've seen programmers truly believe: #define BEGIN { #define END } improves their C code. Fortunately, that was ridiculed out of existence in the 1980s, but the more subtle abuses persist with their ardent defenders. I used to use a lot of macros in my C code, and a few years back made an effort to remove them all from the dmd source code. The result was very satisfactory. I've seen entire code bases abandoned because of macros after the original developer left.
Jan 15
next sibling parent reply Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Wednesday, 16 January 2019 at 05:32:51 UTC, Walter Bright 
wrote:
 On 1/15/2019 10:39 AM, Jacob Carlborg wrote:
 Perhaps we shouldn't support user defined types or functions 
 either ;)
You deliberately wrote that, and I'm confident you'd never try to pass that off as good work. With macros, however, programmers are convinced they are creating models of clarity. I've seen programmers truly believe: #define BEGIN { #define END } improves their C code. Fortunately, that was ridiculed out of existence in the 1980s, but the more subtle abuses persist with their ardent defenders. I used to use a lot of macros in my C code, and a few years back made an effort to remove them all from the dmd source code. The result was very satisfactory. I've seen entire code bases abandoned because of macros after the original developer left.
I'm pretty sure Jacob is talking about a completely different type of macro (i.e. not textual substitution), AST macros. I'd be interested to see how close we could get if we allowed mixin template to contain expression as well as declarations (obviously these could only be instantiated in function contexts). Anyway something to play around with at DConf.
Jan 15
next sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/15/2019 11:08 PM, Nicholas Wilson wrote:
 I'm pretty sure Jacob is talking about a completely different type of macro 
 (i.e. not textual substitution), AST macros.
I understand he means AST macros, but they aren't fundamentally different in the characteristic I'm talking about.
 I'd be interested to see how close we could get if we allowed mixin template
to 
 contain expression as well as declarations (obviously these could only be 
 instantiated in function contexts). Anyway something to play around with at
DConf.
I won't discourage you to play around with it, but I don't think it's what D needs in the near future.
Jan 16
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2019-01-16 08:08, Nicholas Wilson wrote:

 I'm pretty sure Jacob is talking about a completely different type of 
 macro (i.e. not textual substitution), AST macros.
Yeah, I should come up with a new name than "macro". A soon as Walter sees the word "macro", regardless of its meaning in the context, he will throw his hands in the air and run the other way. -- /Jacob Carlborg
Jan 16
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2019-01-16 06:32, Walter Bright wrote:

 You deliberately wrote that, and I'm confident you'd never try to pass 
 that off as good work.
Yes. I'm showing it's possible to write bad code in all programming languages with all (most) features. Macros are not required for that.
 With macros, however, programmers are convinced they are creating models 
 of clarity. I've seen programmers truly believe:
 
      #define BEGIN {
      #define END }
 
 improves their C code. Fortunately, that was ridiculed out of existence 
 in the 1980s, but the more subtle abuses persist with their ardent 
 defenders. I used to use a lot of macros in my C code, and a few years 
 back made an effort to remove them all from the dmd source code. The 
 result was very satisfactory.
 
 I've seen entire code bases abandoned because of macros after the 
 original developer left.
D has done a great job of replacing the C preprocessor with alternative features. These include: "import", "debug" and "version". These features are great and don't need much improvement. They take care of the stuff that is really difficult to avoid the preprocessor in C for. Then we have the other stuff: macros. To insert code at the instantiation point. For this, D has string mixins and template mixins. This is where D is lacking some features. For example, it's not possible to insert a symbol with a string mixin that the surrounding scope at the instantiation point cannot access. For example, you want to insert two symbols, but the surrounding code should only have access to one of the symbols, the other one is a helper symbol to the first one. This is not possible today. Unfortunately that doesn't stop anyone from trying to come up with there own workarounds and solutions, like generating some obfuscated symbol name. It's not gonna make it less accessible, just less likely to collide with an existing symbol. It's also not possible to insert a symbol that refers to another symbol in another module without risking a symbol conflict in the local scope. There's a word for this, mixins are not hygienic. While D improves a lot on the C preprocessor it didn't reach all the way to cross the finish line. -- /Jacob Carlborg
Jan 16
prev sibling next sibling parent reply Mike Franklin <slavo5150 yahoo.com> writes:
On Monday, 14 January 2019 at 05:31:27 UTC, Paul Backus wrote:

 When something like an object system is made part of the 
 language (or at the very least, the standard library), it 
 becomes a focal point [2] that the community can coordinate 
 around. Due to the diverse, distributed nature of any 
 programming-language community, trying to coordinate through 
 explicit communication is not really a viable option, so having 
 these kinds of focal points is very important if we want to be 
 able to work together on anything.

 [1] http://winestockwebdesign.com/Essays/Lisp_Curse.html
 [2] https://en.wikipedia.org/wiki/Focal_point_(game_theory)
I think D's structs are a sufficient object system for such a focal point. With design by introspection, `alias`, templates, `alias this`, `static if`, CTFE, mixins, and a few new D features, classes would be unnecessary. Rust and Zig are pretty good examples of this. D's implementation could even be improved to keep its runtime, yet still allow D to be used as I'm suggesting, without introducing any breakage for anyone. I made some significant progress in that direction when I was working on the compiler in the 2017~2018 timeframe, but my abilities ultimately fell short, and I couldn't see a way forward without support. Mike
Jan 14
next sibling parent reply aberba <karabutaworld gmail.com> writes:
On Monday, 14 January 2019 at 10:06:48 UTC, Mike Franklin wrote:
 On Monday, 14 January 2019 at 05:31:27 UTC, Paul Backus wrote:

 When something like an object system is made part of the 
 language (or at the very least, the standard library), it 
 becomes a focal point [2] that the community can coordinate 
 around. Due to the diverse, distributed nature of any 
 programming-language community, trying to coordinate through 
 explicit communication is not really a viable option, so 
 having these kinds of focal points is very important if we 
 want to be able to work together on anything.

 [1] http://winestockwebdesign.com/Essays/Lisp_Curse.html
 [2] https://en.wikipedia.org/wiki/Focal_point_(game_theory)
I think D's structs are a sufficient object system for such a focal point. With design by introspection, `alias`, templates, `alias this`, `static if`, CTFE, mixins, and a few new D features, classes would be unnecessary. Rust and Zig are pretty good examples of this.
Do people really use Rust in production beyond the safety die hards (of course Mozilla and few uses here and there, mostly C guys...lowlevel purists)? Its such a weird,complicated and academic lang... doubt it'll ever be mainstream like D is supposed to be.
Jan 14
parent JN <666total wp.pl> writes:
On Monday, 14 January 2019 at 13:07:35 UTC, aberba wrote:
 Do people really use Rust in production beyond the safety die 
 hards (of course Mozilla and few uses here and there, mostly C 
 guys...lowlevel purists)? Its such a weird,complicated and 
 academic lang... doubt it'll ever be mainstream like D is 
 supposed to be.
Actually, a lot of people do. Many big companies are getting interested in Rust and many game developers are investigating its capabilities. Rust seems to be mostly appealing to C/C++ programmers who are looking for an alternative.
Jan 14
prev sibling parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Monday, 14 January 2019 at 10:06:48 UTC, Mike Franklin wrote:
 On Monday, 14 January 2019 at 05:31:27 UTC, Paul Backus wrote:

 When something like an object system is made part of the 
 language (or at the very least, the standard library), it 
 becomes a focal point [2] that the community can coordinate 
 around. Due to the diverse, distributed nature of any 
 programming-language community, trying to coordinate through 
 explicit communication is not really a viable option, so 
 having these kinds of focal points is very important if we 
 want to be able to work together on anything.

 [1] http://winestockwebdesign.com/Essays/Lisp_Curse.html
 [2] https://en.wikipedia.org/wiki/Focal_point_(game_theory)
I think D's structs are a sufficient object system for such a focal point. With design by introspection, `alias`, templates, `alias this`, `static if`, CTFE, mixins, and a few new D features, classes would be unnecessary. Rust and Zig are pretty good examples of this. D's implementation could even be improved to keep its runtime, yet still allow D to be used as I'm suggesting, without introducing any breakage for anyone. I made some significant progress in that direction when I was working on the compiler in the 2017~2018 timeframe, but my abilities ultimately fell short, and I couldn't see a way forward without support. Mike
Killing classes will kill my interest and investment in D. Alex.
Jan 14
parent reply Atila Neves <atila.neves gmail.com> writes:
On Monday, 14 January 2019 at 14:59:03 UTC, 12345swordy wrote:
 On Monday, 14 January 2019 at 10:06:48 UTC, Mike Franklin wrote:
 On Monday, 14 January 2019 at 05:31:27 UTC, Paul Backus wrote:

 [...]
I think D's structs are a sufficient object system for such a focal point. With design by introspection, `alias`, templates, `alias this`, `static if`, CTFE, mixins, and a few new D features, classes would be unnecessary. Rust and Zig are pretty good examples of this. D's implementation could even be improved to keep its runtime, yet still allow D to be used as I'm suggesting, without introducing any breakage for anyone. I made some significant progress in that direction when I was working on the compiler in the 2017~2018 timeframe, but my abilities ultimately fell short, and I couldn't see a way forward without support. Mike
Killing classes will kill my interest and investment in D. Alex.
He's not saying "kill classes in D", he's saying an OOP system in D could be implemented from primitives and classes don't need to be a language feature, similar to CLOS in Common Lisp.
Jan 15
next sibling parent Neia Neutuladh <neia ikeran.org> writes:
On Tue, 15 Jan 2019 11:59:58 +0000, Atila Neves wrote:
 He's not saying "kill classes in D", he's saying an OOP system in D
 could be implemented from primitives and classes don't need to be a
 language feature, similar to CLOS in Common Lisp.
As long as the syntax and behavior don't change, the error messages are good, and the compile-time overhead is similar, I won't complain.
Jan 15
prev sibling parent reply welkam <wwwelkam gmail.com> writes:
On Tuesday, 15 January 2019 at 11:59:58 UTC, Atila Neves wrote:
 He's not saying "kill classes in D", he's saying an OOP system 
 in D could be implemented from primitives and classes don't 
 need to be a language feature, similar to CLOS in Common Lisp.
For some people writing OOP means writing keyword class.
Jan 15
parent reply 12345swordy <alexanderheistermann gmail.com> writes:
On Tuesday, 15 January 2019 at 17:29:12 UTC, welkam wrote:
 On Tuesday, 15 January 2019 at 11:59:58 UTC, Atila Neves wrote:
 He's not saying "kill classes in D", he's saying an OOP system 
 in D could be implemented from primitives and classes don't 
 need to be a language feature, similar to CLOS in Common Lisp.
For some people writing OOP means writing keyword class.
I am not interested in OOP as a library feature rather then a built in feature. Let not repeat the same mistakes as c++. If there were a dip that involves deprecating class, expect me to be very vocal in regards to opposing it.
Jan 15
parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/15/2019 11:39 AM, 12345swordy wrote:
 If there were a dip that involves 
 deprecating class,
I wouldn't worry about that getting very far :-)
Jan 16
prev sibling next sibling parent JN <666total wp.pl> writes:
On Monday, 14 January 2019 at 05:31:27 UTC, Paul Backus wrote:
 [1] http://winestockwebdesign.com/Essays/Lisp_Curse.html
This part always feels familiar to me in D (just replace Lisp with D and Haskell with say Rust): Answer: The Lisp Curse kicks in. Every second or third serious Lisp hacker will roll his own implementation of lazy evaluation, functional purity, arrows, pattern matching, type inferencing, and the rest. Most of these projects will be lone-wolf operations. Thus, they will have eighty percent of the features that most people need (a different eighty percent in each case). They will be poorly documented. They will not be portable across Lisp systems. Some will show great promise before being abandoned while the project maintainer goes off to pay his bills. Several will beat Haskell along this or that dimension (again, a different one in each case), but their acceptance will be hampered by flame wars on the comp.lang.lisp Usenet group. also this one: I saw this 10 years ago when looking for a GUI to my Lisp. No problem, there were 9 different offerings. The trouble was that none of the 9 were properly documented and none were bug free. Basically each person had implemented his own solution and it worked for him so that was fine.
Jan 14
prev sibling parent bachmeier <no spam.net> writes:
On Monday, 14 January 2019 at 05:31:27 UTC, Paul Backus wrote:

 Scheme is probably the language that takes this idea of a 
 minimal "core language" with powerful metaprogramming 
 facilities the furthest, and the result is a fragmented 
 ecosystem that makes writing portable, non-trivial programs 
 close to impossible. (See "The Lisp Curse" [1].)
Much as I hate to disagree with folks on the internet, this is an explanation in search of an example. Scheme was originally created as a toy language so Steele and Sussman could have an object oriented language with actors.[1] It later turned out to be a good language for SICP. Macros did not even appear in the Scheme standard until R4RS, and they were not part of the standard until R5RS in 1998, 23 years after initial work started on Scheme. That's not to say that individual implementations didn't have Common Lisp macros prior to R5RS, but the metaprogramming thing was more of a Common Lisp thing than a Scheme thing. To me, it's obvious why Scheme has never taken off. It wasn't created as a language for widespread commercial usage. That was the realm of Common Lisp, and to some extent Common Lisp succeeded. CL was not killed by excessive use of macros. I'll also note that R started as a dialect of Scheme, but it was designed for practical use from the start, and it has millions of users. D has little hope of ever achieving the popularity of R. You can do all kinds of metaprogramming with R. I got tired of R's lack of proper tail call support, so added a working implementation of Clojure's recur in a couple of hours. Extrapolating from Scheme to D is simply not the best use of one's time. [1] See page 33 of https://dreamsongs.com/Files/HOPL2-Uncut.pdf
Jan 14
prev sibling parent reply bachmeier <no spam.net> writes:
On Monday, 14 January 2019 at 03:58:37 UTC, Mike Franklin wrote:

 Because design by introspection allows us to "assemble programs 
 atomically", perhaps high-level language features like classes 
 and interfaces can become obsolete, and the language itself can 
 be reduced simpler primitives that don't require the overhead 
 of a runtime.
Only a small sliver of programming involves anything where "overhead of a runtime" is an issue. I hope you intend this comment as pertaining to Better C usage.
Jan 14
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 14 January 2019 at 14:56:00 UTC, bachmeier wrote:
 Only a small sliver of programming involves anything where 
 "overhead of a runtime" is an issue. I hope you intend this 
 comment as pertaining to Better C usage.
Real D is the true better C. These improvements can improve in various situations. That said though, I'd be against removing built-in classes and interfaces. They are useful in a lot of places built in... though I kinda wish the runtime code was a bit thinner and lighter too.
Jan 14
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/14/19 10:57 AM, Adam D. Ruppe wrote:
 On Monday, 14 January 2019 at 14:56:00 UTC, bachmeier wrote:
 Only a small sliver of programming involves anything where "overhead 
 of a runtime" is an issue. I hope you intend this comment as 
 pertaining to Better C usage.
Real D is the true better C. These improvements can improve in various situations. That said though, I'd be against removing built-in classes and interfaces. They are useful in a lot of places built in... though I kinda wish the runtime code was a bit thinner and lighter too.
Some of the old crufty features of classes can be jettisoned like toString and toHash, and object.factory. -Steve
Jan 14
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Jan 14, 2019 at 03:57:36PM +0000, Adam D. Ruppe via
Digitalmars-d-announce wrote:
 On Monday, 14 January 2019 at 14:56:00 UTC, bachmeier wrote:
 Only a small sliver of programming involves anything where "overhead
 of a runtime" is an issue. I hope you intend this comment as
 pertaining to Better C usage.
Real D is the true better C. These improvements can improve in various situations. That said though, I'd be against removing built-in classes and interfaces. They are useful in a lot of places built in...
Yeah, much as I'm a big promoter of struct-based range-based template style D code, classes and interfaces do still have their place. When you need runtime dynamic polymorphism, it just makes sense to use classes and interfaces instead of trying to bandage your way around structs and CT introspection. I'm still searching for a theoretical model that would bridge the gap between the two and make one unified model, but for now, they each still have their place.
 though I kinda wish the runtime code was a bit thinner and lighter
 too.
Yeah, the whole thing about the monitor field IMO is an unnecessary burden on a use case that isn't always needed. If synchronized classes or whatever needs it, then it should be an ABI specific to synchronized classes. Everybody else shouldn't need to pay tax on it if they never actually need to use it. T -- Shin: (n.) A device for finding furniture in the dark.
Jan 14
prev sibling next sibling parent reply Guillaume Piolat <first.last gmail.com> writes:
On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei Alexandrescu 
wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0

 If nothing else please watch the opening story, it's true and 
 quite funny :o).

 Now as to the talk, as you could imagine, it touches on another 
 language as well...


 Andrei
About the adoption and success of DbI libraries: - Buried inside your talks there are lots of hard-earned principles: "What's missing is as important as what's here" "Big interfaces are good" etc... We have a lack of DbI designers such as yourself or Vladimir so a short text that teach how to design with DbI could be in order. I redirect people to "std::allocator is to allocation what std::vector is to vexation" because it seems to be the only tutorial on this. Other people often lack interest because of real or perceived template bloat, and it's critical. - I think it's important to emphasize CTFE over template instantiations because (per Stefan's measurements) template instantiations are a lot slower and CTFE is already surprisingly faster than template meta-programming, and on the road to become even faster with the superbly needed newCTFE.
Jan 14
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Jan 14, 2019 at 08:38:39PM +0000, Guillaume Piolat via
Digitalmars-d-announce wrote:
[...]
 Other people often lack interest because of real or perceived template
 bloat, and it's critical.
 
 - I think it's important to emphasize CTFE over template
 instantiations because (per Stefan's measurements) template
 instantiations are a lot slower and CTFE is already surprisingly
 faster than template meta-programming, and on the road to become even
 faster with the superbly needed newCTFE.
I think another angle of attack that AFAICT has been mostly overlooked is for the compiler to recognize certain common template patterns, and optimize away intermediate template instantiations that are not actually necessary. Not every template instantiation requires wholesale copying of the AST. I surmise certain patterns of templates could be profitably turned into some kind of compile-time executed code. T -- Без труда не выловишь и рыбку из пруда.
Jan 14
prev sibling next sibling parent reply Ben Jones <fake fake.fake> writes:
On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei Alexandrescu 
wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0

 If nothing else please watch the opening story, it's true and 
 quite funny :o).

 Now as to the talk, as you could imagine, it touches on another 
 language as well...


 Andrei
A lot of the questions were about documenting the hook API and catching misspelling errors when defining a hook. It seems like it would be nice if you could list the hook method names a static array or dictionary or struct containing a field for each method, etc. One each for the required and optional methods. The hook author could grab the name/signature of the method they're intending to implement from that data structure and any misspellings would be caught immediately. Is it possible to declare a function whose name is a CTFE computed string?
Jan 14
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Monday, 14 January 2019 at 21:08:50 UTC, Ben Jones wrote:
 Is it possible to declare a function whose name is a CTFE 
 computed string?
Yes, if you do it with a string mixin.
Jan 14
parent Neia Neutuladh <neia ikeran.org> writes:
On Mon, 14 Jan 2019 21:12:48 +0000, Paul Backus wrote:
 On Monday, 14 January 2019 at 21:08:50 UTC, Ben Jones wrote:
 Is it possible to declare a function whose name is a CTFE computed
 string?
Yes, if you do it with a string mixin.
And more simply, you can declare a function with a hard-coded name, then use an alias to expose it under a different name.
Jan 14
prev sibling parent reply Andre Pany <andre s-e-a-p.de> writes:
On Monday, 14 January 2019 at 21:08:50 UTC, Ben Jones wrote:
 On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei 
 Alexandrescu wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0

 If nothing else please watch the opening story, it's true and 
 quite funny :o).

 Now as to the talk, as you could imagine, it touches on 
 another language as well...


 Andrei
A lot of the questions were about documenting the hook API and catching misspelling errors when defining a hook. It seems like it would be nice if you could list the hook method names a static array or dictionary or struct containing a field for each method, etc. One each for the required and optional methods. The hook author could grab the name/signature of the method they're intending to implement from that data structure and any misspellings would be caught immediately. Is it possible to declare a function whose name is a CTFE computed string?
For ranges there are concepts like Input Range. A struct/class must have several methods to be compliant. You can check the compliance using function isInputRange https://dlang.org/library/std/range/primitives/is_input_range.html Maybe something similiar can be done here. Not checking individual methods, but concepts... Kind regards Andre
Jan 14
parent Ben Jones <fake fake.fake> writes:
On Monday, 14 January 2019 at 21:22:32 UTC, Andre Pany wrote:
 On Monday, 14 January 2019 at 21:08:50 UTC, Ben Jones wrote:
 On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei 
 Alexandrescu wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0

 If nothing else please watch the opening story, it's true and 
 quite funny :o).

 Now as to the talk, as you could imagine, it touches on 
 another language as well...


 Andrei
A lot of the questions were about documenting the hook API and catching misspelling errors when defining a hook. It seems like it would be nice if you could list the hook method names a static array or dictionary or struct containing a field for each method, etc. One each for the required and optional methods. The hook author could grab the name/signature of the method they're intending to implement from that data structure and any misspellings would be caught immediately. Is it possible to declare a function whose name is a CTFE computed string?
For ranges there are concepts like Input Range. A struct/class must have several methods to be compliant. You can check the compliance using function isInputRange https://dlang.org/library/std/range/primitives/is_input_range.html Maybe something similiar can be done here. Not checking individual methods, but concepts... Kind regards Andre
I don't think that's quite sufficient because a hook may/may not have the optional methods, and could have extra stuff. What you want is to specify per method "this method is part of the hook interface," which as I type it kind of sounds like the job of an annotation...
Jan 14
prev sibling next sibling parent reply aliak <something something.com> writes:
On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei Alexandrescu 
wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0

 If nothing else please watch the opening story, it's true and 
 quite funny :o).

 Now as to the talk, as you could imagine, it touches on another 
 language as well...


 Andrei
Awesome talk! As usual. Regarding this quote: "The ruby guy next to you is writing just as crappy code..." I don't think that's really correct. The reference is code complete, which is published in 93 (i.e. no java, no ruby, before the stl even?) and i believe (just googled this so may be wrong) the reference in that book is from a 1977 paper on programmer quality and productivity and the 2004 edition of code complete changes the number form 15 to 50 / 1000 to 1 .. 25 / 1000, but references the same paper afaik. Here's a more recent study: http://rayb.info/uploads/cacm2017-lang.pdf Here's an article that summarizes it -> https://www.i-programmer.info/news/98-languages/11184-which-languages-are-bug-prone.html Quote from article: "The languages with the strongest positive coefficients - meaning associated with a greater number of defect fixes are C++, C, and Objective-C, also PHP and Python. On the other hand, Clojure, Haskell, Ruby and Scala all have significant negative coefficients implying that these languages are less likely than average to result in defect fixing commits." Also this is more anecdotal, but for example going from objective-c to swift, the number of non-application-specific bugs per line (regardless of whether or not that's even a good measure 🤷‍♂️), i feel, has gone down by an exaggerated order of magnitude. Cheers, - Ali
Jan 14
parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 15 January 2019 at 05:18:45 UTC, aliak wrote:
 Quote from article:

 "The languages with the strongest positive coefficients - 
 meaning associated with a greater number of defect fixes are 
 C++, C, and Objective-C, also PHP and Python.  On the other 
 hand, Clojure, Haskell, Ruby and Scala all have significant 
 negative coefficients implying that these languages are less 
 likely than average to result in defect fixing commits."
Does this take into account the experience of the programmers writing in each language? Given their relative popularity, I imagine PHP and Python have many more beginning programmers writing code in them than Haskell and Clojure.
Jan 14
parent aliak <something something.com> writes:
On Tuesday, 15 January 2019 at 06:57:28 UTC, Paul Backus wrote:
 On Tuesday, 15 January 2019 at 05:18:45 UTC, aliak wrote:
 Quote from article:

 "The languages with the strongest positive coefficients - 
 meaning associated with a greater number of defect fixes are 
 C++, C, and Objective-C, also PHP and Python.  On the other 
 hand, Clojure, Haskell, Ruby and Scala all have significant 
 negative coefficients implying that these languages are less 
 likely than average to result in defect fixing commits."
Does this take into account the experience of the programmers writing in each language? Given their relative popularity, I imagine PHP and Python have many more beginning programmers writing code in them than Haskell and Clojure.
Not that I saw in the paper no. But that is a good point.
Jan 14
prev sibling parent reply John Carter <john.carter taitradio.com> writes:
On Saturday, 12 January 2019 at 15:51:03 UTC, Andrei Alexandrescu 
wrote:
 https://youtube.com/watch?v=tcyb1lpEHm0
 Now as to the talk, as you could imagine, it touches on another
Somebody on the C++ side has written a reply.... https://brevzin.github.io/c++/2019/01/15/if-constexpr-isnt-broken/ Although looking at the implementation of std::conditional in the type_traits header makes me sad... I would love to see the whole checkedint thing in C++ side by side with the d code (and generated -Os object code). Conversely I'd love to see a Rust implementation too :-) Given that I have probably written a lot more C++ code in my life than d... ...I do find it remarkable that I can read the d code quite easily without reaching for the reference manual, but to make sense of his C++, it sends me trawling around cppreference.com I find Andrei's claim that checkint with a void hook reverts to int is amazing, and would love to verify that at the assembly level for both the C++ and d implementations.
Jan 16
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Jan 16, 2019 at 11:43:19PM +0000, John Carter via
Digitalmars-d-announce wrote:
[...]
 Given that I have probably written a lot more C++ code in my life than
 d...
 
 ...I do find it remarkable that I can read the d code quite easily
 without reaching for the reference manual, but to make sense of his
 C++, it sends me trawling around cppreference.com
Yes, that's one of the outstanding qualities of D, and one that I was immensely impressed with when I perused the Phobos source code for the first time. After having (tried to) read glibc's source code (if you never have, I advise you not to unless you're a jaded, hardened, hardcore C professional -- it's *not* for the faint of heart), it was like a breath of fresh air. D does have its warts and dark corners, but I think on the readability front it has scored a home run compared to the equivalent C/C++ code.
 I find Andrei's claim that checkint with a void hook reverts to int is
 amazing, and would love to verify that at the assembly level for both
 the C++ and d implementations.
This is actually quite trivial in D. I'm too lazy to actually check the checkedint source code, but I'd surmise it's something as simple as: template CheckedInt(alias hook) { static if (is(typeof(hook) == void)) alias CheckedInt = int; else { struct CheckedInt { ... // actual CheckedInt implementation here } } } or something along these lines. Standard D practice. (I daren't even try to imagine what I'd have to do to make this work in C++. After having worked with C++ for about 2 decades or so, I don't have many good things to say about it, nor do I expect very much from it anymore.) T -- Windows 95 was a joke, and Windows 98 was the punchline.
Jan 16
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/16/2019 4:19 PM, H. S. Teoh wrote:
 On Wed, Jan 16, 2019 at 11:43:19PM +0000, John Carter via
Digitalmars-d-announce wrote:
 ...I do find it remarkable that I can read the d code quite easily
 without reaching for the reference manual, but to make sense of his
 C++, it sends me trawling around cppreference.com
Yes, that's one of the outstanding qualities of D, and one that I was immensely impressed with when I perused the Phobos source code for the first time.
Bartosz Milewski is a C++ programmer and a Haskell fan. He once gave a presentation at NWCPP where he wrote a few lines of Haskell code. Then, he showed the same code written using C++ template metaprogramming. The Haskell bits in the C++ code were highlighted in red. It was like a sea of grass with a shrubbery here and there. Interestingly, by comparing the red dots in the C++ code with the Haskell code, you could understand what the C++ was doing. Without the red highlighting, it was a hopeless wall of < > :-) Since I mention Bartosz, I should link to his blog: https://bartoszmilewski.com/
Jan 16
next sibling parent Meta <jared771 gmail.com> writes:
On Thursday, 17 January 2019 at 01:59:29 UTC, Walter Bright wrote:
 Bartosz Milewski is a C++ programmer and a Haskell fan. He once 
 gave a presentation at NWCPP where he wrote a few lines of 
 Haskell code. Then, he showed the same code written using C++ 
 template metaprogramming.

 The Haskell bits in the C++ code were highlighted in red. It 
 was like a sea of grass with a shrubbery here and there. 
 Interestingly, by comparing the red dots in the C++ code with 
 the Haskell code, you could understand what the C++ was doing. 
 Without the red highlighting, it was a hopeless wall of < > :-)

 Since I mention Bartosz, I should link to his blog:

 https://bartoszmilewski.com/
It was an article on Bartosz's blog where I first found out about D. I think this was the first one: "The more things change, the more we need “immutable”" https://bartoszmilewski.com/2009/01/
Jan 16
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Jan 16, 2019 at 05:59:29PM -0800, Walter Bright via
Digitalmars-d-announce wrote:
[...]
 Bartosz Milewski is a C++ programmer and a Haskell fan. He once gave a
 presentation at NWCPP where he wrote a few lines of Haskell code.
 Then, he showed the same code written using C++ template
 metaprogramming.
 
 The Haskell bits in the C++ code were highlighted in red. It was like
 a sea of grass with a shrubbery here and there. Interestingly, by
 comparing the red dots in the C++ code with the Haskell code, you
 could understand what the C++ was doing. Without the red highlighting,
 it was a hopeless wall of < > :-)
[...] I don't know Haskell, but I've worked with Scheme (another Lisp dialect / derivative) a little, and sometimes I feel like the core of my logic is little bits of shrubbery lost in an ocean of parentheses. :-P T -- I don't trust computers, I've spent too long programming to think that they can get anything right. -- James Miller
Jan 17
prev sibling parent reply bpr <brogoff gmail.com> writes:
On Thursday, 17 January 2019 at 01:59:29 UTC, Walter Bright wrote:
 On 1/16/2019 4:19 PM, H. S. Teoh wrote:
 On Wed, Jan 16, 2019 at 11:43:19PM +0000, John Carter via 
 Digitalmars-d-announce wrote:
 [...]
Yes, that's one of the outstanding qualities of D, and one that I was immensely impressed with when I perused the Phobos source code for the first time.
Bartosz Milewski is a C++ programmer and a Haskell fan. He once gave a presentation at NWCPP where he wrote a few lines of Haskell code. Then, he showed the same code written using C++ template metaprogramming. The Haskell bits in the C++ code were highlighted in red. It was like a sea of grass with a shrubbery here and there. Interestingly, by comparing the red dots in the C++ code with the Haskell code, you could understand what the C++ was doing. Without the red highlighting, it was a hopeless wall of < > :-)
Was that a pre C++11 version of C++, or a more modern one? It would be instructive to see that example with C++17 or even 20 and D next to each other.
Jan 17
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Thursday, 17 January 2019 at 16:06:39 UTC, bpr wrote:
 On Thursday, 17 January 2019 at 01:59:29 UTC, Walter Bright 
 wrote:
 Bartosz Milewski is a C++ programmer and a Haskell fan. He 
 once gave a presentation at NWCPP where he wrote a few lines 
 of Haskell code. Then, he showed the same code written using 
 C++ template metaprogramming.

 The Haskell bits in the C++ code were highlighted in red. It 
 was like a sea of grass with a shrubbery here and there. 
 Interestingly, by comparing the red dots in the C++ code with 
 the Haskell code, you could understand what the C++ was doing. 
 Without the red highlighting, it was a hopeless wall of < > :-)
Was that a pre C++11 version of C++, or a more modern one? It would be instructive to see that example with C++17 or even 20 and D next to each other.
The presentation was given at BoostCon 2011, and is (at least partially) available on youtube [1]. There is also a blog post from 2009, "What Does Haskell Have to Do with C++?" [2] that uses the same format, and presumably covers the same material. The examples in the blog post were tested with "the GNU C++ compiler v. 4.4.1 with the special switch -std=c++0x", which according to the GCC documentation [3] includes many (but not all) features from C++11. [1] https://www.youtube.com/watch?v=GjhsSzRtTGY [2] https://bartoszmilewski.com/2009/10/21/what-does-haskell-have-to-do-with-c/ [3] https://gcc.gnu.org/gcc-4.4/cxx0x_status.html
Jan 17
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
FYI, this whole subthread of B Revzin is NOT in my newsgroup reader. I 
only saw it because I was browsing the forum web page.

What happened?

-Steve
Jan 17
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jan 17, 2019 at 06:03:07PM +0000, Paul Backus via
Digitalmars-d-announce wrote:
[...]
 [2]
 https://bartoszmilewski.com/2009/10/21/what-does-haskell-have-to-do-with-c/
[...] Haha, seems D did better than C++ in this respect, but not quite at the level of Haskell. The C++ example of a template that takes templates and arguments and declares another template is a perfect example of why C++ template syntax is utterly horrible for doing these sorts of things. Coming back to the D example at the end, I totally agree with the sentiment that D templates, in spite of their significant improvements over C++ syntax, ultimately still follow the same recursive model. Yes, you can use CTFE to achieve the same thing at runtime, but it's not the same thing, and CTFE cannot manipulate template argument lists (aka AliasSeq aka whatever it is you call them). This lack of symmetry percolates down the entire template system, leading to the necessity of the hack that Bartosz refers to. Had template argument lists / AliasSeq been symmetric w.r.t. runtime list manipulation, we would've been able to write a foreach loop that manipulates the AliasSeq in the most readable way without needing to resort to hacks or recursive templates. // Lately, as I've been pondering over these fundamental language design issues, I've become more and more convinced that symmetry is the way to go. And by symmetry, I mean the mathematical sense of being "the same under some given mapping (i.e., transformation or substitution)". Why is C++ template syntax such a mess to work with? Because it's a separate set of syntax and idioms grafted onto the original core language with little or no symmetry between them. Where the core language uses < and > as comparison operators, template syntax uses < and > as delimiters. This asymmetry leads to all kinds of nastiness, like earlier versions of C++ being unable to parse `templateA<templateB<int>>` properly (the >> gets wrongly lexed as a bitshift operator). An intervening space is required to work around this asymmetry. This is just one trivial example. A more fundamental example, which also afflicts D, is that the template instantiation mechanism is inherently recursive rather than iterative, so when you need to write a loop, you have to paraphrase it as a recursive template. This is asymmetric with the runtime part of the language, where constructs like `foreach` are readily available to express the desired semantics. On a different note, the same principle of symmetry applies to built-in types vs. user-defined types. In TDPL Andrei alludes to programmers disliking built-in types having "magic" behaviour that's different from user-defined types. Why the dislike? Because of asymmetry. Built-in types have special behaviour that cannot be duplicated by user-defined types, so when you want the special behaviour but built-in types don't quite meet your needs, you find yourself without any recourse. It is frustrating because the reasoning goes "if built-in type X can have magic behaviour B, why can't user-defined type Y have behaviour B too?" The desire for behaviour B to be possible both for built-in types and user-defined types stems from the desire for symmetry. Why is alias this so powerful? Because it lets a new type Y behave as if it were an existing type X -- it's symmetry. Similarly, the Liskov Substitution Principle is essentially a statement of symmetry in the universe of OO polymorphism. Why is the Unix "everything is a file" abstraction so useful? Because of symmetry: whether it's a physical file, a network socket, or pipe, it exposes the same API. Code that works with the data don't have to care about what kind of object it is; it can simply use the API that is symmetric across different types of objects. Similarly, why are D ranges so powerful? Because they make containers, data sources, data generators, etc., symmetric under the range API operations. It allows code to be decoupled from the details of the concrete types, and focus directly on the problem domain. Why does the GC simplify many programming tasks so much? Because it makes every memory-allocated object symmetric w.r.t. memory management: you stop worrying about whether something is stack-allocated or heap-allocated, whether it has cycles, or whether somebody else still holds a reference to it -- you focus on the problem domain and let the GC do its job. At a higher level: in the old days, programming languages used to distinguish between functions and procedures (and maybe some languages still do, but they seem rare these days). But eventually this distinction was ditched in favor of things like returning `void` (C, C++, Java, D), or some other equivalent construct. Why? So that instead of having two similar but asymmetric units of code encapsulation, everything is just a "function" (it just so happens some functions don't return a meaningful value). IOW, introduce symmetry, get rid of the asymmetry. On the flip side, when there is lack of symmetry, many problems arise. I already mentioned C++ template syntax and how it's asymmetric w.r.t. the imperative part of the language. The recursive nature of templates in both C++ and D, as opposed to iterative runtime constructs like foreach, is another example of asymmetry that leads to ugly / convoluted code where the corresponding runtime code has no such issue. Auto-decoding is another prime example of asymmetry causing problems: all other arrays are ranges of their element type, but narrow strings are not. While it still does support the range API (and is symmetric in that sense with other ranges), this internal asymmetry causes all sorts of trouble: performance troubles, tons of special-case code (just look at Phobos range algorithms and see how many special cases pertain to narrow strings -- and how many bugs were caused in the interim), introducing a difference between .count and .indexOf (it's the reason for the very existence of .indexOf where .count would have sufficed, had narrow strings been symmetric in range element type w.r.t. other ranges). There's also APIs that are hard to use because they are asymmetric to other APIs that you happen to be using. For example, if a hypothetical D library sported an API that used .next and .empty instead of the standard .empty, .front, .popFront, then the asymmetry with the range API common throughout D code would cause all sorts of impedance mismatch problems. And one would naturally gravitate towards writing a wrapper around this incompatible API that replicated the range API. IOW, you fix the problem by *introducing symmetry* where there was asymmetry. A more minor point is the overloading of keywords to mean different things, like `void` meaning "does not return" in one context, yet in a different context `void*` means "can point to anything". Or the various overloaded meanings of `static` in D, which is a rat's nest of strange exceptions and ad hoc semantics that have no real pattern, you just have to separately learn what it means in each context. Also, the asymmetry of function attributes (there is `pure`, but no `impure`; there's `nothrow` but not `throwing`, you write safe with a but pure doesn't have a ). A mostly minor syntactical point, but it seems to keep coming up every time somebody new encounters them, and the complaints seem disproportionate to the actual importance of the issue. Why? Asymmetry. And in some cases, it leads to not-so-trivial issues (which I won't repeat here). And the oft-proposed solution? Introduce symmetry. And operator overloading. In spite of all the problems associated with operator overloading, it's still practically a necessity when you're implementing arithmetical types. A matrix library in C requires very ugly syntax to work with; in C++ and D, we naturally gravitate towards operator overloading. Why? Because we desire symmetry with built-in arithmetic types. Sure I could write: result = prod(matrix1, sub(matrix2, matrix3)); but I would much rather write: result = matrix1 * (matrix2 - matrix3); And why UFCS? Because of symmetry: every subsequent operation on a range can be written as syntactically top-level function call, rather than the asymmetry of nesting every operation inside the previous one: myrange.map!(...) .filter!(...) .joiner .array; vs. array(joiner(filter!(...)(map!(...)(myrange)))); I could go on and on. But this principle of symmetry seems to me to underlie many fundamental language design issues. There seems to be a general trend where the more symmetry there is, the smoother a language feature will be and the less problems will be caused; whereas the less symmetry there is, the more troubles, ugly workarounds, tendency towards bugs, or just general unhappiness there will be. I don't know if it's possible for a programming language to be *completely* symmetrical -- maybe Lisp and Haskell come pretty close -- but the further you deviate from symmetry, the more troubles you can expect. As a corollary, with every new language change, it would be worthwhile to evaluate how it affects the overall symmetry of the language. Does it add more symmetry, or does it introduce asymmetry (syntactic, semantic, etc.) w.r.t. existing features? It seems to me that people rarely consider this aspect of language design, esp. when they are trying to fix what they perceive to be an important oversight in the language, but IMO the issue of symmetry is certainly worth careful consideration alongside the other usual factors. T -- English has the lovely word "defenestrate", meaning "to execute by throwing someone out a window", or more recently "to remove Windows from a computer and replace it with something useful". :-) -- John Cowan
Jan 17
next sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 1/17/19 2:31 PM, H. S. Teoh wrote:
 On Thu, Jan 17, 2019 at 06:03:07PM +0000, Paul Backus via
Digitalmars-d-announce wrote:
 [...]
 [2]
 https://bartoszmilewski.com/2009/10/21/what-does-haskell-have-to-do-with-c/
[...] Haha, seems D did better than C++ in this respect, but not quite at the level of Haskell. The C++ example of a template that takes templates and arguments and declares another template is a perfect example of why C++ template syntax is utterly horrible for doing these sorts of things. Coming back to the D example at the end, I totally agree with the sentiment that D templates, in spite of their significant improvements over C++ syntax, ultimately still follow the same recursive model. Yes, you can use CTFE to achieve the same thing at runtime, but it's not the same thing, and CTFE cannot manipulate template argument lists (aka AliasSeq aka whatever it is you call them). This lack of symmetry percolates down the entire template system, leading to the necessity of the hack that Bartosz refers to. Had template argument lists / AliasSeq been symmetric w.r.t. runtime list manipulation, we would've been able to write a foreach loop that manipulates the AliasSeq in the most readable way without needing to resort to hacks or recursive templates.
well, there was no static foreach for that article (which I admit I didn't read, but I know what you mean). But it's DEFINITELY not as easy as it could be: import std.conv; alias AliasSeq(P...) = P; template staticMap(alias Transform, Params...) { alias seq0 = Transform!(Params[0]); static foreach(i; 1 .. Params.length) { mixin("alias seq" ~ i.to!string ~ " = AliasSeq!(seq" ~ (i-1).to!string ~ ", Transform!(Params[" ~ i.to!string ~ "]));"); } mixin("alias staticMap = seq" ~ (Params.length-1).to!string ~ ";"); } alias Constify(T) = const(T); void main() { alias someTypes = AliasSeq!(int, char, bool); pragma(msg, staticMap!(Constify, someTypes)); // (const(int), const(char), const(bool)) } Note, that this would be a LOT easier with string interpolation... mixin("alias seq${i} = AliasSeq!(seq${i-1}, Transform!(Params[${i}]));".text); -Steve
Jan 17
parent reply Mark <smarksc gmail.com> writes:
On Thursday, 17 January 2019 at 20:47:38 UTC, Steven 
Schveighoffer wrote:
 well, there was no static foreach for that article (which I 
 admit I didn't read, but I know what you mean).

 But it's DEFINITELY not as easy as it could be:

 import std.conv;

 alias AliasSeq(P...) = P;

 template staticMap(alias Transform, Params...)
 {
     alias seq0 = Transform!(Params[0]);
     static foreach(i; 1 .. Params.length)
     {
        mixin("alias seq" ~ i.to!string ~ " = AliasSeq!(seq" ~ 
 (i-1).to!string ~ ", Transform!(Params[" ~ i.to!string ~ 
 "]));");
     }
     mixin("alias staticMap = seq" ~ (Params.length-1).to!string 
 ~ ";");
 }

 alias Constify(T) = const(T);
 void main()
 {
     alias someTypes = AliasSeq!(int, char, bool);
     pragma(msg, staticMap!(Constify, someTypes)); // 
 (const(int), const(char), const(bool))
 }

 Note, that this would be a LOT easier with string 
 interpolation...

 mixin("alias seq${i} = AliasSeq!(seq${i-1}, 
 Transform!(Params[${i}]));".text);

 -Steve
Why not do away with AliasSeq and use strings all the way? string Constify(string type) { // can add input checks here return "const(" ~ type ~ ")"; } void main() { import std.algorithm : map; enum someTypes = ["int", "char", "bool"]; enum constTypes = map!Constify(someTypes); mixin(constTypes[0] ~ "myConstInt = 42;"); // int myConstInt = 42; } Represent types as strings, CTFE them as you see fit, and output a string that can then be mixin'ed to use the actual type. :)
Jan 18
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Jan 18, 2019 at 08:03:48PM +0000, Mark via Digitalmars-d-announce wrote:
[...]
 Why not do away with AliasSeq and use strings all the way?
 
 string Constify(string type)
 {
     // can add input checks here
     return "const(" ~ type ~ ")";
 }
 
 void main()
 {
     import std.algorithm : map;
     enum someTypes = ["int", "char", "bool"];
     enum constTypes = map!Constify(someTypes);
     mixin(constTypes[0] ~ "myConstInt = 42;"); // int myConstInt = 42;
 }
 
 Represent types as strings, CTFE them as you see fit, and output a
 string that can then be mixin'ed to use the actual type. :)
That would work, but it would also suffer from all the same problems as macro-based programming in C. The compiler would be unable to detect when you accidentally pasted type names together where you intended to be separate, the strings may not actually represent real types, and generating code from pasting / manipulating strings is very error-prone. And you could write very unmaintainable code like pasting partial tokens together as strings, etc., which makes it hard for anyone else (including yourself after 3 months) to understand just what the code is trying to do. Generally, you want some level of syntactic / semantic enforcement by the compiler when you manipulate lists (or whatever other structures) of types. T -- INTEL = Only half of "intelligence".
Jan 18
parent Mark <smarksc gmail.com> writes:
On Friday, 18 January 2019 at 20:29:08 UTC, H. S. Teoh wrote:
 That would work, but it would also suffer from all the same 
 problems as macro-based programming in C.  The compiler would 
 be unable to detect when you accidentally pasted type names 
 together where you intended to be separate, the strings may not 
 actually represent real types, and generating code from pasting 
 / manipulating strings is very error-prone. And you could write 
 very unmaintainable code like pasting partial tokens together 
 as strings, etc., which makes it hard for anyone else 
 (including yourself after 3 months) to understand just what the 
 code is trying to do.

 Generally, you want some level of syntactic / semantic 
 enforcement by the compiler when you manipulate lists (or 
 whatever other structures) of types.


 T
Well, it's the approach Andrei laid out in his DConf 2018 talk: https://youtu.be/-0jcE9B5kjs?t=2641 The advantage is how simple it is, and that it only uses existing language constructs. But, indeed, the problems you mention are not insignificant.
Jan 19
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Friday, 18 January 2019 at 20:03:48 UTC, Mark wrote:
 [...]

 Represent types as strings, CTFE them as you see fit, and 
 output a string that can then be mixin'ed to use the actual 
 type. :)
Two problems: 1) Mixing in a string is unhygienic. If two modules (or two scopes in the same module) define types with the same name, you might get the wrong one. 2) You can't mixin the name of a Voldemort type.
Jan 18
prev sibling next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Thursday, 17 January 2019 at 19:31:24 UTC, H. S. Teoh wrote:
 On Thu, Jan 17, 2019 at 06:03:07PM +0000, Paul Backus via 
 Digitalmars-d-announce wrote: [...]
 [2] 
 https://bartoszmilewski.com/2009/10/21/what-does-haskell-have-to-do-with-c/
[...] Coming back to the D example at the end, I totally agree with the sentiment that D templates, in spite of their significant improvements over C++ syntax, ultimately still follow the same recursive model. Yes, you can use CTFE to achieve the same thing at runtime, but it's not the same thing, and CTFE cannot manipulate template argument lists (aka AliasSeq aka whatever it is you call them). This lack of symmetry percolates down the entire template system, leading to the necessity of the hack that Bartosz refers to. Had template argument lists / AliasSeq been symmetric w.r.t. runtime list manipulation, we would've been able to write a foreach loop that manipulates the AliasSeq in the most readable way without needing to resort to hacks or recursive templates.
For 2 years I have pondered this problem, and I did come up with a solution. It's actually not that hard to have CTFE interact with type-tuples. You can pass them as function parameters, or return them if you wish. Of course a type-tuple returning ctfe function, is compile-time only. This solved one more problem that ctfe has: helper functions required for ctfe can only be omitted from the binary, if you use the trick of putting them into a module which is the import path but never explicitly given on the command line. newCTFE has the facility to be extended for this, and implementing type-functions is at least on my personal roadmap. At Dconf 2018 Andrei and Walter said, a DIP which is substantiated enough might make it. However due to lack of time, (and productivity-reducing internal changes) it will take some time until I can get started on this. Also I plan for newCTFE to be in shape before I add type-manipulation abilities. Cheers, Stefan P.S. There is one caveat: because of how type-functions work they cannot, you cannot create a non-anonymous symbol inside a type-function, because there is no way to infer a mangle. You can however create an anonymous symbol and alias it inside a template body, which gives it a mangle and it can behave like a regular symbol.
Jan 17
next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jan 17, 2019 at 10:20:24PM +0000, Stefan Koch via
Digitalmars-d-announce wrote:
 On Thursday, 17 January 2019 at 19:31:24 UTC, H. S. Teoh wrote:
[...]
 Coming back to the D example at the end, I totally agree with the
 sentiment that D templates, in spite of their significant
 improvements over C++ syntax, ultimately still follow the same
 recursive model. Yes, you can use CTFE to achieve the same thing at
 runtime, but it's not the same thing, and CTFE cannot manipulate
 template argument lists (aka AliasSeq aka whatever it is you call
 them).  This lack of symmetry percolates down the entire template
 system, leading to the necessity of the hack that Bartosz refers to.
 
 Had template argument lists / AliasSeq been symmetric w.r.t. runtime
 list manipulation, we would've been able to write a foreach loop
 that manipulates the AliasSeq in the most readable way without
 needing to resort to hacks or recursive templates.
 
For 2 years I have pondered this problem, and I did come up with a solution. It's actually not that hard to have CTFE interact with type-tuples. You can pass them as function parameters, or return them if you wish. Of course a type-tuple returning ctfe function, is compile-time only.
YES! This is the way it should be. Type-tuples become first class citizens, and you can pass them around to functions and return them from functions, the only stipulation being that they can only exist at compile-time, so it's an error to use them at runtime. In other words, they become symmetric to other built-in language types, and can be manipulated by conventional means, instead of being an oddball exception with special-case behaviour that requires special-case syntax dedicated to manipulating them. Again, the root of the problem is asymmetry, and the solution is to make it symmetric.
 This solved one more problem that ctfe has:
 helper functions required for ctfe can only be omitted from the
 binary, if you use the trick of putting them into a module which is
 the import path but never explicitly given on the command line.
Exactly. Yet another problem caused by the asymmetry of type-tuples w.r.t. other built-in types, and naturally solved by making them symmetric.
 newCTFE has the facility to be extended for this, and implementing
 type-functions is at least on my personal roadmap.
Awesome.
 At Dconf 2018 Andrei and Walter said, a DIP which is substantiated
 enough might make it.
 However due to lack of time, (and productivity-reducing internal
 changes) it will take some time until I can get started on this.
 
 Also I plan for newCTFE to be in shape before I add type-manipulation
 abilities.
Yes, let's please get the Minimum Viable Product of newCTFE merged into master first, before we expand the scope (and delay the schedule :-P) yet again! [...]
 P.S. There is one caveat: because of how type-functions work they
 cannot, you cannot create a non-anonymous symbol inside a
 type-function, because there is no way to infer a mangle.

 You can however create an anonymous symbol and alias it inside a
 template body, which gives it a mangle and it can behave like a
 regular symbol.
Interesting. Is it possible to assign a "fake" mangle to type functions that never actually gets emitted into the object code, but just enough to make various internal compiler stuff that needs to know the mangle work properly? T -- Why do conspiracy theories always come from the same people??
Jan 17
next sibling parent Stefan Koch <uplink.coder googlemail.com> writes:
On Thursday, 17 January 2019 at 22:44:08 UTC, H. S. Teoh wrote:
 On Thu, Jan 17, 2019 at 10:20:24PM +0000, Stefan Koch via 
 Digitalmars-d-announce wrote:
 P.S. There is one caveat: because of how type-functions work 
 they cannot, you cannot create a non-anonymous symbol inside a 
 type-function, because there is no way to infer a mangle.

 You can however create an anonymous symbol and alias it inside 
 a template body, which gives it a mangle and it can behave 
 like a regular symbol.
Interesting. Is it possible to assign a "fake" mangle to type functions that never actually gets emitted into the object code, but just enough to make various internal compiler stuff that needs to know the mangle work properly?
No this is not possible, a symbol which is only used at compile-time is actually really rare. Actually If the symbol is constrained to a compile-time only context (e.g. inside is() or taking the .sizeof) this problem does not arise, and it could be allowed. Imagine you want to return a struct type which has all the fields of a given base struct but adds a member.
 module ct_helper;
alias f(alias baseT, alias newMemberType, string newMember_name) { struct Extended { baseT base; mixin("newMemberType " ~ newMemberName); } return typeof(Extended.init); }
------
 module user
struct S1 { int x; } alias S2 = f!(S1, float, "y") // looks like a template-instantiation but it's not!, I am just reusing it, to not confuse the parser to much. which mangle should this get? S2 ? - doesn't work there is no mangle for an alias. ct_helper.f.Extended? doesn't work if we call the type-function again with diffrent arguments make it an anonymous type ? - If we do that than this means that the type-function is no longer pure as two anonymous types can never Equal each other include the arguments to the type-function and it's parameters in the mangle? - that's possible but type-functions are not meant to leave any sign of their existence in order to not introduce ABI issues. In short for now I'd rather side-step the problem by not allowing freshly minted types to escape into a runtime context without going through a template wrapper (which also handles caching and has proper behavior in is-expressions).
Jan 17
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2019-01-17 23:44, H. S. Teoh wrote:

 YES!  This is the way it should be.  Type-tuples become first class
 citizens, and you can pass them around to functions and return them from
 functions
No no no, not only type-tuples, you want types to be first class citizens. This makes it possible to store a type in a variable, pass it to and return from functions. Instead of a type-tuple, you want a regular array of types. Then it would be possible to use the algorithms in std.algorithm to manipulate the arrays. I really hate that today one needs to resort to things like staticMap and staticIndexOf. Of course, if we both get tuples and types as first class citizens it would be possible to store types in these tuples as well. But a tuple is usually immutable and I'm not sure if it would be possible to use std.algorithm on that. It would be awesome to be able to do things like this: type foo = int; type bar(type t) { return t; } auto u = [byte, short, int, long].map!(t => t.unsigned).array; assert(u == [ubyte, ushort, uint, ulong]; -- /Jacob Carlborg
Jan 18
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Fri, Jan 18, 2019 at 11:23:11AM +0100, Jacob Carlborg via
Digitalmars-d-announce wrote:
 On 2019-01-17 23:44, H. S. Teoh wrote:
 
 YES!  This is the way it should be.  Type-tuples become first class
 citizens, and you can pass them around to functions and return them
 from functions
No no no, not only type-tuples, you want types to be first class citizens. This makes it possible to store a type in a variable, pass it to and return from functions. Instead of a type-tuple, you want a regular array of types. Then it would be possible to use the algorithms in std.algorithm to manipulate the arrays. I really hate that today one needs to resort to things like staticMap and staticIndexOf.
Yes, that would be the next level of symmetry. :-D Types as first class citizens would eliminate another level of distinctions that leads to the necessity of staticMap, et al. But it will also require changing the language in a much more fundamental, invasive way. So I'd say, let's take it one step at a time. Start with first-class type-tuples, then once that's ironed out and working well, take it to the next level and have first-class types. Trying to leap from here to there in one shot is probably a little too ambitious, with too high a chance of failure. [...]
 It would be awesome to be able to do things like this:
 
 type foo = int;
 
 type bar(type t)
 {
     return t;
 }
 
 auto u = [byte, short, int, long].map!(t => t.unsigned).array;
 assert(u == [ubyte, ushort, uint, ulong];
[...] Yes this would be awesome. But in order to avoid unmanageable complexity of implementation, all of this would have to be compile-time only constructs. T -- Your inconsistency is the only consistent thing about you! -- KD
Jan 18
prev sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Friday, 18 January 2019 at 10:23:11 UTC, Jacob Carlborg wrote:
 On 2019-01-17 23:44, H. S. Teoh wrote:

 YES!  This is the way it should be.  Type-tuples become first 
 class
 citizens, and you can pass them around to functions and return 
 them from
 functions
No no no, not only type-tuples, you want types to be first class citizens. This makes it possible to store a type in a variable, pass it to and return from functions. Instead of a type-tuple, you want a regular array of types. Then it would be possible to use the algorithms in std.algorithm to manipulate the arrays. I really hate that today one needs to resort to things like staticMap and staticIndexOf. Of course, if we both get tuples and types as first class citizens it would be possible to store types in these tuples as well. But a tuple is usually immutable and I'm not sure if it would be possible to use std.algorithm on that. It would be awesome to be able to do things like this: type foo = int; type bar(type t) { return t; } auto u = [byte, short, int, long].map!(t => t.unsigned).array; assert(u == [ubyte, ushort, uint, ulong];
Yes, you will be able to do exactly what you describe above. type-tuples are strictly a superset of types; which also include true compile-time constants. (e.g. things you can use to instantiate a template with.) Within type functions you are able to create `alias[]` which is in some ways equivalent to type-tuple (and will be converted to one upon being returned outside of compile-functions),which you can append to if you own it and type functions can also take other type-functions as parameters. Therefore it's perfectly possible to implement staticMap in terms of type functions. I already did the semantic sanity checks, and it shows promise. The only difference that type-functions have from what you describe is that it does not need to occupy a keyword 'type'. Cheers, Stefan
Jan 18
parent reply Jacob Carlborg <doob me.com> writes:
On 2019-01-18 20:28, Stefan Koch wrote:

 The only difference that type-functions have from what you describe is 
 that it does not need to occupy a keyword 'type'.
You're using "alias" instead of my "type" keyword? -- /Jacob Carlborg
Jan 18
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Friday, 18 January 2019 at 20:32:35 UTC, Jacob Carlborg wrote:
 On 2019-01-18 20:28, Stefan Koch wrote:

 The only difference that type-functions have from what you 
 describe is that it does not need to occupy a keyword 'type'.
You're using "alias" instead of my "type" keyword?
yes. After all what type-functions do when returning types, is to return an alias. Since it's unable to create types this is all it can do.
Jan 18
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2019-01-17 23:44, H. S. Teoh wrote:

 Interesting.  Is it possible to assign a "fake" mangle to type functions
 that never actually gets emitted into the object code, but just enough
 to make various internal compiler stuff that needs to know the mangle
 work properly?
Not sure that would be possible. I tries to a support for pragma(mangle) on alias declarations. That opened a can of worms. It turns out that the compiler is using the mangling of a type to compare types internally. -- /Jacob Carlborg
Jan 18
prev sibling parent Johannes Loher <johannesloher fg4f.de> writes:
Am 17.01.19 um 23:20 schrieb Stefan Koch:
 For 2 years I have pondered this problem, and I did come up with a
 solution.
 It's actually not that hard to have CTFE interact with type-tuples.
 You can pass them as function parameters, or return them if you wish.
 Of course a type-tuple returning ctfe function, is compile-time only.
 This solved one more problem that ctfe has:
 helper functions required for ctfe can only be omitted from the binary,
 if you use the trick of putting them into a module which is the import
 path but never explicitly given on the command line.
 newCTFE has the facility to be extended for this, and implementing
 type-functions is at least on my personal roadmap.
 
 At Dconf 2018 Andrei and Walter said, a DIP which is substantiated
 enough might make it.
 However due to lack of time, (and productivity-reducing internal
 changes) it will take some time until I can get started on this.
 
 Also I plan for newCTFE to be in shape before I add type-manipulation
 abilities.
 
 Cheers,
 
 Stefan
 
 P.S. There is one caveat: because of how type-functions work they
 cannot, you cannot create a non-anonymous symbol inside a type-function,
 because there is no way to infer a mangle.
 You can however create an anonymous symbol and alias it inside a
 template body, which gives it a mangle and it can behave like a regular
 symbol.
 
 
This is one of the most exciting things i have read in recent times!
Jan 17
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 1/17/2019 11:31 AM, H. S. Teoh wrote:
 [...]
Thanks for the thoughtful and well-written piece. But there is a counterpoint: symmetry in mathematics is one thing, but symmetry in human intuition is not. Anytime one is dealing in human interfaces, one runs into this. I certainly did with the way imports worked in D. The lookups worked exactly the same for any sort of symbol lookup. I thought it was great. But I was unable to explain it to others. Nobody could understand it when I said imported symbol lookup worked exactly like any lookup in a name space. They universally said it was "unintuitive", filed bug reports, etc. Eventually, I had to give it up. Now import lookup follows special different rules, people are happy, and I learned (again) that symmetry doesn't always produce the best outcomes. User interfaces (and programming languages certainly are user interfaces) are hard and (ironically) are anything but intuitive to design.
Jan 17
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Thu, Jan 17, 2019 at 05:32:52PM -0800, Walter Bright via
Digitalmars-d-announce wrote:
 On 1/17/2019 11:31 AM, H. S. Teoh wrote:
 [...]
Thanks for the thoughtful and well-written piece. But there is a counterpoint: symmetry in mathematics is one thing, but symmetry in human intuition is not. Anytime one is dealing in human interfaces, one runs into this. I certainly did with the way imports worked in D. The lookups worked exactly the same for any sort of symbol lookup. I thought it was great. But I was unable to explain it to others. Nobody could understand it when I said imported symbol lookup worked exactly like any lookup in a name space. They universally said it was "unintuitive", filed bug reports, etc. Eventually, I had to give it up. Now import lookup follows special different rules, people are happy, and I learned (again) that symmetry doesn't always produce the best outcomes.
Alas, it's true, it's true, 100% symmetry is, in the general case, impossible to achieve. If we wanted 100% mathematical symmetry, one could argue lambda calculus is the best programming language ever, because it's Turing complete, the syntax is completely uniform with no quirky exceptions, and the semantics are very clearly defined with no ambiguity anywhere. Unfortunately, these very characteristics are also what makes lambda calculus impossible to work with for anything but the most trivial of programs. It's completely unmaintainable, extremely hard to read, and has non-trivial semantics that vary wildly from the smallest changes to the code. For a human-friendly programming language, any symmetry must necessarily be based on human expectations. Unfortunately, as you learned, human intuition varies from person to person, and indeed, is often inconsistent even with the same person, so trying to maximise symmetry in a way that doesn't become "counterintuitive" is a pretty tall order. As somebody (perhaps you) said once, in Boeing's experience with designing intuitive UIs, they discovered that what people consider "intuitive" is partly colored by their experience, and their experience is in turn shaped by the UIs they interact with. So it's a feedback loop, which means what's "intuitive" is not some static set of rules (even allowing for arbitrarily complex rules), but it's a *moving target*, the hardest thing to design for. What's considered "intuitive" today may be considered "totally counter-intuitive" 10 years from now. In the case of imports, I'd argue that the problem is with how people understand the word "import". From a compiler's POV, the simplest, most straightforward (and most symmetric!) definition is "pull in the symbols into the local scope". Unfortunately, that's not the understanding most programmers have. Perhaps in an older, bygone era people might have been more open to that sort of definition, but in this day and age of encapsulation and modularity, "pull in symbols into the local scope" does not adequately capture people's expectations: it violates encapsulation, in the following sense: symbols from the imported module shadow local symbols, which goes against the expectation that the local module is an encapsulated thing, inviolate from outside interference. It breaks the expectation of encapsulation. It breaks the symmetry that everywhere else, outside code cannot interfere with local symbols. Consequently, the expectation is that imported symbols are somehow "second class" relative to local symbols -- imported symbols don't shadow local symbols (unless you explicitly ask for it), and thus encapsulation is preserved (in some sense). So we have here a conflict between different axes of symmetry: the symmetry of every module being an inviolate, self-contained unit (encapsulation), and the symmetry of having the same rules for symbol lookup no matter where the symbol came from. It's a toss-up which axis of symmetry one should strive for, and which one should be compromised. I'd say the general principle ought to be that the higher-level symmetry (encapsulation of modules) should override the lower-level symmetry (the mechanics of symbol lookup). But this is easy to say because hindsight is 20/20; it's not so simple at the time of decision-making because it's not obvious which symmetries are in effect and what their relative importance should be. And there's always the bugbear that symmetry from the implementor's (compiler writer's) POV does not necessarily translate to symmetry from the user's (language user's) POV. Still, I'd say that in a general sense, symmetry ought to be a relatively high priority as far as designing language features or adding/changing features are concerned. Adding a new feature with little regard for how it interacts with existing features, what new corner cases it might introduce, etc., is generally a bad idea. Striving for maximal symmetry should at least give you a ballpark idea for where things should be headed, even if working out the details is generally not so straightforward. It may be that you will discover mutually-exclusive symmetries that, no matter which way you take, will lead to trouble later on. Conflicts of this sort usually cannot be fully resolved without essentially gutting the entire system to the core and rebuilding from scratch, which usually is not a practical thing to do. So we're stuck with imperfection. Nevertheless, IMO we should still strive for perfection, even if it's ultimately unattainable. Being slightly closer to perfection is better than being far off.
 User interfaces (and programming languages certainly are user
 interfaces) are hard and (ironically) are anything but intuitive to
 design.
Yes, it's very unintuitive to design intuitive interfaces. :-D It's the paradox of user-interface design. T -- Life is too short to run proprietary software. -- Bdale Garbee
Jan 18
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/17/2019 8:06 AM, bpr wrote:
 Was that a pre C++11 version of C++, or a more modern one?
pre C++11
Jan 17
prev sibling parent Walter Bright <newshound2 digitalmars.com> writes:
On 1/16/2019 3:43 PM, John Carter wrote:
 Somebody on the C++ side has written a reply....
 
 https://brevzin.github.io/c++/2019/01/15/if-constexpr-isnt-broken/
From the article: D (with corrections): static if (maxLength < 0xFFFE) { alias CellIdx = uint16_t; } else { alias CellIdx = uint32_t; } C++: static constexpr auto get_type() { if constexpr (maxLength < 0xFFFE) { return type<uint16_t>; } else { return type<uint32_t>; } } using CellIdx = decltype(get_type())::type; 1. you've got to write a function separately for every declaration you want to declare in a conditional. Imagine doing 4 or 5 of these. 2. imagine this: static if (condition) int x; ... static if (condition) ++x; The C++ idiom would require (along with creating another function) creating a dummy x declaration for the (omitted) else branch of the static if. Doable, but ugly. It kinda reminds me of the C diehards who showed you can write virtual function dispatch in C. It's remarkable that these things can be done in C++, but the amount of "noise" and "boilerplate" in the solutions make them pretty hard to read.
Jan 16