digitalmars.D - [OT] What are D's values?
- Paul Backus (51/51) Oct 04 2021 In ["Rust and Other Interesting Things"][1], Bryan Cantrill talks
- WebFreak001 (15/23) Oct 04 2021 I have thought about it and think (ROT13):
- jfondren (36/53) Oct 04 2021 The explanation for why a language might have X as its #1 value
- Paul Backus (14/28) Oct 04 2021 I would say that it is overly reductive to insist that there is
- russhy (6/6) Oct 04 2021 With D is get insanely quick iteration time, my project rebuilds
- Steven Schveighoffer (5/11) Oct 04 2021 As you add more templates and CTFE, this quickly goes away though.
- SealabJaster (8/10) Oct 04 2021 A sad truth about D. Hopefully core.reflect will help alleviate
- jfondren (26/31) Oct 04 2021 You can have a shockingly fast compiler if you want it. You can
- SealabJaster (48/49) Oct 04 2021 Definitely a more fun way to look at things :)
- H. S. Teoh (24/43) Oct 04 2021 To be fair, though, even with extensive template use, compile times
- =?UTF-8?Q?Ali_=c3=87ehreli?= (15/19) Oct 04 2021 That comes up often. (Fresh case: One of my colleagues who had to adopt
- Adam D Ruppe (6/8) Oct 04 2021 And it can meet you where you are
- russhy (4/18) Oct 04 2021 You don't need to abuse any of them to build nice program
- Paulo Pinto (2/8) Oct 05 2021 Delphi, Eiffel and Common Lisp.
- =?UTF-8?Q?Ali_=c3=87ehreli?= (31/34) Oct 04 2021 This thread is on-topic. :)
- Dukc (22/25) Oct 04 2021 ```d
- David Gileadi (3/11) Oct 04 2021 This message was a reference type containing protected values.
- Dukc (3/4) Oct 05 2021 Huh, what did you try to do? I tested the snippet before posting
- David Gileadi (2/8) Oct 05 2021 Sorry, it was my poor attempt at wordplay. Please ignore.
- Imperatorn (2/10) Oct 05 2021 I got the joke anyway 😅
- Walter Bright (20/31) Oct 04 2021 Interestingly, left off is one thing that D does very well at: plasticit...
- SealabJaster (18/19) Oct 04 2021 I find code that does Design by Introspection tends to be very
- Tejas (7/26) Oct 04 2021 Can you please list any resources on DbI?
- SealabJaster (12/13) Oct 04 2021 I'm not actually too sure about anything specifically on DbI.
- Tejas (4/17) Oct 04 2021 That's okay, parts 1-4 a literally a click away :D
- Paul Backus (15/25) Oct 04 2021 Design by introspection is when you have templated code
- Tejas (14/44) Oct 04 2021 Is that seriously all there is to it? I see Andrei saying in his
- Paul Backus (20/34) Oct 04 2021 Whenever you write a `static if` statement, you end up with two
- Tejas (5/15) Oct 04 2021 So the key is getting expressiveness and performance while
- Patrick Schluter (6/14) Oct 05 2021 What really happens in other languages is either proliferation of
- WebFreak001 (6/21) Oct 05 2021 a thing I notice from the C code where I work is that there is a
- H. S. Teoh (15/19) Oct 07 2021 I also noticed from the C code at my job that there's a lot of
- =?UTF-8?Q?Ali_=c3=87ehreli?= (19/20) Oct 04 2021 Even before hearing the term Design by Introspection, I was showing
- H. S. Teoh (164/168) Oct 04 2021 [...]
- Tejas (10/17) Oct 04 2021 ...
- Matheus (5/9) Oct 04 2021 I'm not the OP but I'd like to say thank you very much for taking
- zjh (4/6) Oct 04 2021 ......
- Guillaume Piolat (17/20) Oct 05 2021 The construction of the allocator library in
- Tejas (10/34) Oct 06 2021 So apart from the plasticity that others mention, why do you feel
- Guillaume Piolat (34/43) Oct 07 2021 My field is largely dominated by C++. So I'll talk largely about
- Imperatorn (9/14) Oct 07 2021 Interesting. I'm on the fence on if I should pick up C++ again or
- Paulo Pinto (9/25) Oct 07 2021 Metal Shading Language, CUDA, working on LLVM or GCC internals,
- Imperatorn (2/13) Oct 07 2021 Yep, that's the unfortunate truth
- Dukc (16/37) Oct 07 2021 Interesting! How do D and C++ cultures differ?
- Guillaume Piolat (14/22) Oct 07 2021 LDC rivals clang of course. On what metric do you think it
- IGotD- (23/29) Oct 07 2021 I've given up on C++ unless it is embedded programming. C++ is
- Tejas (6/14) Oct 08 2021 Chances of Rust taking over that segment?
- IGotD- (19/24) Oct 08 2021 Rust is already partially eating up the marketshare of C/C++.
- bauss (5/8) Oct 08 2021 C# works excellent on every platform that it runs on, regardless
- Imperatorn (3/10) Oct 08 2021 We use C# today on Windows and Linux. Works great. x86 win /
- IGotD- (8/10) Oct 08 2021 May I also ask how the licensing situation for C# with cross
- Imperatorn (2/14) Oct 08 2021 https://dotnet.microsoft.com/platform/free
- russhy (8/8) Oct 08 2021 Why do you guys compare D to C#, if there is one language you
- Adam Ruppe (2/4) Oct 08 2021 D is realistically best suited to be a more fun C#.
- russhy (3/7) Oct 08 2021 If it had a competing GC, i'd say yes, but that's not the case
- Greg Strong (16/17) Oct 08 2021 Yes, absolutely! I made the move from C++ to C# about 15 years
- Paulo Pinto (33/51) Oct 08 2021 I still find Roslyn compiler plugins and the code generators
- Imperatorn (5/39) Oct 09 2021 Omg my eyes. Don't rough up C#, use D instead 😅
- Paulo Pinto (2/8) Oct 09 2021 Sure when D's ecosystem catches up.
- Imperatorn (4/14) Oct 09 2021 Soon (tm) *dreaming*
- SealabJaster (34/35) Oct 09 2021 It'd definitely be a nice surprise if the leadership announced
- SealabJaster (8/9) Oct 09 2021 I guess a point I wanted to drive home is that these would be
- Imperatorn (2/8) Oct 09 2021 Agreed. Would be nice if you could streamline stuff a bit more
- Dukc (140/143) Oct 10 2021 Lol, I haven't done this put my C# definitely shows I wish I had
- Dukc (2/4) Oct 10 2021 "but" intended, not "put".
- Imperatorn (12/30) Oct 09 2021 This is kinda where I'm at atm. The *only* thing holding me back
- IGotD- (6/8) Oct 09 2021 That's where I think there are room for improvements.
- Imperatorn (14/23) Oct 09 2021 Agreed, but here I'm talking about the language aspect. There are
- Imperatorn (2/10) Oct 08 2021 Mostly thinking about the language itself, syntax
- Paulo Pinto (26/34) Oct 09 2021 So much disinformation.
- russhy (16/53) Oct 09 2021 vibe-d and hunt helped compete with asp.net and spring, it's a
- Tejas (16/24) Oct 08 2021 I think that could well be one of our strongest advantages
- Imperatorn (2/10) Oct 08 2021 This is why I'm still so ambivalent on what I should do with C++ 😭
- Dukc (16/29) Oct 10 2021 I was thinking about the frontend. Some C++ frontends are so
- max haughton (6/24) Oct 10 2021 C++ has hypernormalized a very language-lawyery way of
- H. S. Teoh (57/62) Oct 07 2021 Speaking for myself only here:
- Tejas (20/81) Oct 08 2021 Yeah JS is a royal pain, but now TS has become a true
- Paul Backus (17/39) Oct 04 2021 I've experienced this too.
- H. S. Teoh (91/113) Oct 04 2021 I've totally experienced this. Some of my personal projects started out
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/7) Oct 04 2021 That is exactly the case! (I wrote my response to H. S. Teoh before
- Walter Bright (2/4) Oct 04 2021 Hmm, I should have read your post first!
- Max Samukha (5/6) Oct 05 2021 To me, that's just another case of abstraction. D's '.' abstracts
- H. S. Teoh (58/65) Oct 05 2021 It's more than just '.' vs '.' and '->', though. That's just one of the
- jfondren (6/17) Oct 05 2021 This is all great, but C is too weak a competitor for it to be
- Imperatorn (3/11) Oct 05 2021 Interesting link about Rust. I think D could/should speak to
- Paulo Pinto (4/13) Oct 05 2021 C has the whole market of UNIX clones, Khronos standards, and
- Walter Bright (4/8) Oct 05 2021 This is why D's test suite is so crucial. We could never improve D witho...
- Max Samukha (2/10) Oct 07 2021 Yeah, D is better than C in that respect.
- Guillaume Piolat (27/28) Oct 05 2021 Pretty much.
- Steven Schveighoffer (22/25) Oct 06 2021 For the most part, it's great!
- bauss (6/33) Oct 06 2021 This is something I agree with. I often come across small
- Walter Bright (4/4) Oct 06 2021 We've known about this ambiguity issue for a long time. Unfortunately, w...
- bauss (3/8) Oct 07 2021 Well D makes up for it with its many other great features :) Tbh.
- H. S. Teoh (28/48) Oct 07 2021 IMO, taking the address of something is a low-level operation that
- Steven Schveighoffer (54/97) Oct 08 2021 To give more context, it is solely for this little function:
- Arjan (33/46) Oct 08 2021 From my experience:
- =?UTF-8?Q?Ali_=c3=87ehreli?= (22/27) Oct 08 2021 Are you sure it worked? Because Bjarne thinks "it doesn't work". ;)
- Arjan (12/25) Oct 11 2021 Thanks for the links. Interesting but I do not concur with those
- =?UTF-8?Q?Ali_=c3=87ehreli?= (5/10) Oct 11 2021 Neither do I. My sarcastic winky was too subtle? :)
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (8/11) Nov 03 2021 Did we view the same clip? He seemed to argue that reimplementing
- Jon Degenhardt (8/11) Oct 08 2021 Not the focus of the subsequent thread, but here are my answers
- Chris Piker (32/34) Oct 08 2021 A little while back I evaluated Go, Rust, D as a replacement for
- Ki Rill (20/21) Oct 10 2021 D is all about choice.
- H. S. Teoh (11/35) Oct 12 2021 +1, one of the things that drew me to D was the choices. It doesn't try
- Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= (20/25) Oct 16 2021 It is not good when you have to read code written by others.
- harakim (15/66) Oct 30 2021 I'm not an expert so I'm a little hesitant to post, but I'd say:
In ["Rust and Other Interesting Things"][1], Bryan Cantrill talks about the importance of a programming language's *values*. Values, he says, are the things a language *prioritizes*--the things it chooses when difficult tradeoffs have to be made. For example: everyone agrees that both "safety" and "performance" are valuable, but when forced to choose, some languages (Java, Python) are willing to trade away some performance for additional safety, whereas others (C, C++) would rather give up safety to gain performance. When we're choosing a programming language, Cantrill tells us, choosing one with the right *values* is just as important as choosing one with the right *features* and *ecosystem*--because values are what determine how those features and ecosystem will develop over time. One slide in his presentation contains a list of things that a programming language might value: Approachability Integrity Robustness Availability Maintainability Safety Compatibility Measurability Security Composability Operability Simplicity Debuggability Performance Stability Expressiveness Portability Thoroughness Extensibility Resiliency Transparency Interoperability Rigor Velocity I thought it might be fun to ask the D community: **which of the above values do you think are the most important to D? Choose no more than 5, and reply with your answer!** I've put my answer below, encoded using [ROT13][2]. Try to come up with your own answer before you read mine, to avoid biasing yourself. [1]: https://www.youtube.com/watch?v=2wZ1pCpJUIM [2]: https://rot13.com/ --- V guvax Q'f svir zbfg vzcbegnag inyhrf ner * Nccebnpunovyvgl - obgu Q'f flagnk naq ynathntr srngherf ner qrfvtarq gb or snzvyvne gb hfref bs bgure cbchyne ynathntrf (r.t., P, Wnin, Clguba, Wninfpevcg). gbhe.qynat.bet zragvbaf n "tenqhny yrneavat pheir" nf na rkcyvpvg qrfvta tbny. * Rkcerffvirarff - jvgu srngherf yvxr grzcyngrf, zvkvaf, naq bcrengbe bireybnqvat (vapyhqvat bcQvfcngpu), Q vf bar bs gur zbfg rkcerffvir ynathntrf guvf fvqr bs Yvfc. * Fnsrgl - abg whfg fnsr, ohg nyfb qrsnhyg vavgvnyvmngvba bs inevnoyrf, obhaqf-purpxvat sbe neenlf, rkprcgvbaf sbe reebe unaqyvat, naq ybgf bs bgure yvggyr qrpvfvbaf. * Cresbeznapr - angvir pbzcvyngvba, bs pbhefr, cyhf ybj-yriry srngherf yvxr enj cbvagref, vayvar nfz, naq ohvyg-va FVZQ bcrengvbaf. * Vagrebcrenovyvgl - abg bayl qbrf Q unir orfg-va-pynff P vagrebc, naq gur qvfgvapgvba bs orvat bar bs gur bayl ynathntrf gb rira *nggrzcg* P++ vagrebc, vg nyfb unf fhccbeg sbe Bowrpgvir-P pynffrf naq PBZ vagresnprf.
Oct 04 2021
On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:[...] I thought it might be fun to ask the D community: **which of the above values do you think are the most important to D? Choose no more than 5, and reply with your answer!** I've put my answer below, encoded using [ROT13][2]. Try to come up with your own answer before you read mine, to avoid biasing yourself. [...]I have thought about it and think (ROT13): 1. Vagrebcrenovyvgl - Q chgf znwbe rssbeg vagb orvat pbzcngvoyr jvgu bgure ynathntrf naq rkvfgvat P pbqr 2. Fnsrgl - vg unf n ybg bs sbphf ba fnsrgl ol pbeerpgarff 3. Irybpvgl - orvat cebqhpgvir naq pbqvat pbqr snfgre vf n ovt cneg bs Q'f punez 4. Rkcerffvirarff - Q pbqr pna ryrtnagyl ercerfrag n ybg bs ceboyrzf va fubeg, rnfl-gb-ernq pbqr 5. Cresbeznapr - Qrfvta bs fghss yvxr enatrf naq znal fgqyvo hgvyf srryf yvxr gurl ner rfcrpvnyyl znqr sbe trarengvat cresrpg pbqr yvxr vg'f unaqjevggra naq jvgu gung tbbq cresbeznapr V unq lbhe svefg cbvag nf zl 6gu pubvpr, ohg qvqa'g guvax vg jnf gung ovt bs n qrfvta tbny, orpnhfr vg'f whfg nobhg snzvyvnevgl naq abg nobhg nccebnpunovyvgl sbe arjpbzref ernyyl.
Oct 04 2021
On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:One slide in his presentation contains a list of things that a programming language might value: Approachability Integrity Robustness Availability Maintainability Safety Compatibility Measurability Security Composability Operability Simplicity Debuggability Performance Stability Expressiveness Portability Thoroughness Extensibility Resiliency Transparency Interoperability Rigor Velocitybut then fall short on X will be that the language is pulled back from full-X by its other values. Someone might argue that Python values Expressiveness, but that its other value of Approachability keeps it from having proper closures. But the actual reason that Python doesn't have proper closures is that Guido thinks they're weird and confusing:Most Python users are unfamiliar with Lisp or Scheme, so the name is confusing; also, there is a widespread misunderstanding that lambda can do things that a nested function can't I think having the two choices side-by-side just requires programmers to think about making a choice that's irrelevant for their program; not having the choice streamlines the thought process.Does a competing value keep Go from permitting an unused module import? When I looked at this and other quirks of go the language seemed to me like the product of Rob Pike deciding that he's had well enough of some specifically unpleasant experiences with code and was just going to make a language where they aren't possible. (I think he could list the names of coworkers next to features of the language. "And I told Jim, 'if I see any go from you it's going to be go *without* your habit of importing the entire world. You know how I know that?'") Does a competing value keep D from supporting boolean expressions in version() tests, or keep D from having AST macros? It's rather that Walter is familiar with the hazards in those directions and wants to stay away from them. So I don't think listing values is enough to describe a language's development. There's also the hazards that the language developers are especially concerned with. D probably has lots of design decisions that can be explained by "we're avoiding this bad outcome of C++". The other day on the discord it was mentioned that C++ will implicitly create a struct as a function parameter but that D doesn't because C++ does that way too much in practice. You could twist this specific antipathy into a value like 'Transparency', but that doesn't explain the design as neatly. And it's not as entertaining to read about. "D has BetterC because we value Interoperability, and because we don't value Integrity that much." is less interesting than "just look at this madness that snuck into dmd when I permitted boolean versions:". Both imagined quotes.
Oct 04 2021
On Monday, 4 October 2021 at 14:30:20 UTC, jfondren wrote:but then fall short on X will be that the language is pulled back from full-X by its other values. Someone might argue that Python values Expressiveness, but that its other value of Approachability keeps it from having proper closures. But the actual reason that Python doesn't have proper closures is that Guido thinks they're weird and confusing:I would say that it is overly reductive to insist that there is only one "actual reason" behind any given decision. Most outcomes have many causes, direct and indirect. The direct, stated reason for Python's lack of closures is that Guido thinks they're weird and confusing. But are other, indirect reasons implied by his argument, like "Python shouldn't have language features that most users are unfamiliar with", and "Python shouldn't have two ways to do the same thing". These indirect reasons are, more or less, expressions of values like Approachability and Simplicity. Obviously you cannot *completely* reduce a language's development process down to a list of values--that would be ridiculous. But it does help to be aware of them.Most Python users are unfamiliar with Lisp or Scheme, so the name is confusing; also, there is a widespread misunderstanding that lambda can do things that a nested function can't I think having the two choices side-by-side just requires programmers to think about making a choice that's irrelevant for their program; not having the choice streamlines the thought process.
Oct 04 2021
With D is get insanely quick iteration time, my project rebuilds in 0.7 seconds (full clean rebuild) None of the existing natively compiled language can offer this, NONE!! This is something people forget to mention, but this is very valuable
Oct 04 2021
On 10/4/21 1:13 PM, russhy wrote:With D is get insanely quick iteration time, my project rebuilds in 0.7 seconds (full clean rebuild) None of the existing natively compiled language can offer this, NONE!! This is something people forget to mention, but this is very valuableAs you add more templates and CTFE, this quickly goes away though. You have to be very religious about what templates you use in order to keep this compile time. -Steve
Oct 04 2021
On Monday, 4 October 2021 at 18:03:58 UTC, Steven Schveighoffer wrote:You have to be very religious about what templates you use in order to keep this compile time.A sad truth about D. Hopefully core.reflect will help alleviate some of these issues in the long run. Also, I believe the person you're responding to is a pure -betterC user (or along those lines? he can correct me if not), so likely don't touch Phobos' templates all too much, which tend to be real time slogs.
Oct 04 2021
On Monday, 4 October 2021 at 18:23:24 UTC, SealabJaster wrote:On Monday, 4 October 2021 at 18:03:58 UTC, Steven Schveighoffer wrote:You can have a shockingly fast compiler if you want it. You can have fully manual memory with RAII and shared/unique pointers if you want them. You can have code that looks like a scripting language and relies heavily on the GC if you want it. You can have code that looks like it's in an FP language if you want it. You can have monadic error handling if you want it a lot. You can have borrow-checked pointers if you want them. But you can't have it all at once. Not in D, where sublanguages containing each of these features is available, and not in any other language, where some features aren't available and others are inescapable. For branding, put a smiley face on this instead of calling it a sad truth. Need to write a tiny static executable to do a single thing fast using low-level OS APIs so that it can achieve paranoid security for the sake of Perl or Python or bash scripts that call this program? Good candidate for BetterC. Want to write a near-throwaway script? Good candidate for 'import std' and tons of allocation. Want to write a daemon to replace a golang server that's too resource intensive? Better candidate for scoped imports and careful design with nogc and nothrow helping you control where work is happening. All that with the 'same' language, rather than "oh I'll use C", "oh I'll use Python", "oh now I can finally use my systems language". Of course I still want faster compilation of std.regex.You have to be very religious about what templates you use in order to keep this compile time.A sad truth about D.
Oct 04 2021
On Monday, 4 October 2021 at 19:35:08 UTC, jfondren wrote:...Definitely a more fun way to look at things :) However trying to get things like this across to people who don't really use D would be tricky. "Why choose D over Python for quick scripts?" "Why choose D over C/C++ for low level code, also something something GC" "Why choose D over Go or Java or even Javascript for backend web dev?" Low level code in particular can be a bit annoying, since D doesn't provide standard collections and lifetime containers for a decent 'get stuff done' ` nogc` experience, but I've ranted about that enough. This is mainly a major issue to me from a library perspective, since libraries don't have a singular interface to rally around. I really wish I could use D everywhere, but I sometimes I just excellent Asp Core and EF Core. Standard configuration interface, standard logging interface, standard dependency injection, which all the other libraries I want will integrate with flawlessly(tm). Since D can technically cover most major aspects of programming, coming up with an answer of these "why" questions, especially when performing comparisons to other languages, is pretty hard due to the broad surface area to cover. Also something something libraries >;3 I definitely do wonder what D would look like with an "insert popular language" user base, from discussions, to ecosystem, and certainly the pain points and pros that people find with the language. But "why" use D? "What" do we offer language wise, ecosystem wise, etc. I feel the "ecosystem" part is the larger part to focus on IMO. We can boast all we want about great native performance; some of the strongest metaprogramming available, all with an easy and clean syntax. But if people can't just 'get things done' then the friction of setting up/writing/creating a binding for the code they need might be too much, so they leave for a different language with everything they need all ready to go, all integrated together, etc. But enough rambling, I'm not even close to an expert on these subjects >:D Anyway, as an attempt to stay on topic, my values from that selection are: 1. Performance 2. Interoperability 3. Robustness 4. Extensibility++++ 5. Expressiveness
Oct 04 2021
On Mon, Oct 04, 2021 at 07:35:08PM +0000, jfondren via Digitalmars-d wrote:On Monday, 4 October 2021 at 18:23:24 UTC, SealabJaster wrote:To be fair, though, even with extensive template use, compile times generally aren't horrible, unless you happen to use code that abuses recursive templates (e.g., certain Phobos modules like std.format, or (ack) std.regex, where the mere act of importing it adds about 1-2 seconds to your compile time). For simple metaprogramming with templates, compile-times are generally still within the realm of <5 seconds or so, which is still magnitudes faster than any non-trivial C++ project I've ever had to deal with. [...]On Monday, 4 October 2021 at 18:03:58 UTC, Steven Schveighoffer wrote:You have to be very religious about what templates you use in order to keep this compile time.A sad truth about D.For branding, put a smiley face on this instead of calling it a sad truth. Need to write a tiny static executable to do a single thing fast using low-level OS APIs so that it can achieve paranoid security for the sake of Perl or Python or bash scripts that call this program? Good candidate for BetterC. Want to write a near-throwaway script? Good candidate for 'import std' and tons of allocation. Want to write a daemon to replace a golang server that's too resource intensive? Better candidate for scoped imports and careful design with nogc and nothrow helping you control where work is happening. All that with the 'same' language, rather than "oh I'll use C", "oh I'll use Python", "oh now I can finally use my systems language".+1, D is so versatile that it easily lends itself to all these diverse use cases. Sometimes it can even adapt itself across these use cases, e.g., a number of my personal projects started out as throwaway single-file, script-like hacks, but eventually developed into full-fledged multi-module, multi-package programs. If I had done this in any other language, it'd have involved rewriting the program from scratch at least 3-4 times. With D, it can gradually and smoothly morph itself from a one-off script into a full-fledged, properly-encapsulated program without missing a beat. Man, I love D.Of course I still want faster compilation of std.regex.:-D T -- Кто везде - тот нигде.
Oct 04 2021
On 10/4/21 4:16 PM, H. S. Teoh wrote:a number of my personal projects started out as throwaway single-file, script-like hacks, but eventually developed into full-fledged multi-module, multi-package programs.That comes up often. (Fresh case: One of my colleagues who had to adopt D programs I had written, tells me he is finding it very easy to morph the code.) Perhaps we should sell D's "morphability", likely with a better marketing name.Man, I love D.You said it right after talking about being able to morph D code. :) I have the same feeling: I secretly wish my colleagues will come up with new requirements so that I will write more fun D code. An anecdote from a past project: A hardware colleague of mine once asked "How come when I ask HW engineers to improve the HW design, they go right ahead and start implementing it but SW people always whine and want to keep the SW design as is?" (The programming languages were C and C++ at that time.) Ali
Oct 04 2021
On Monday, 4 October 2021 at 23:16:00 UTC, H. S. Teoh wrote:+1, D is so versatile that it easily lends itself to all these diverse use casesAnd it can meet you where you are i wrote about this a while ago: http://dpldocs.info/this-week-in-d/Blog.Posted_2021_02_08.html#adam's-thoughts-on-mental-friction (fun fact: that topic was actually what I was originally thinking about doing as the DConf 2014 talk.)
Oct 04 2021
On Monday, 4 October 2021 at 18:03:58 UTC, Steven Schveighoffer wrote:On 10/4/21 1:13 PM, russhy wrote:You don't need to abuse any of them to build nice program My game/engine is the perfect exampleWith D is get insanely quick iteration time, my project rebuilds in 0.7 seconds (full clean rebuild) None of the existing natively compiled language can offer this, NONE!! This is something people forget to mention, but this is very valuableAs you add more templates and CTFE, this quickly goes away though. You have to be very religious about what templates you use in order to keep this compile time. -Steve
Oct 04 2021
On Monday, 4 October 2021 at 17:13:58 UTC, russhy wrote:With D is get insanely quick iteration time, my project rebuilds in 0.7 seconds (full clean rebuild) None of the existing natively compiled language can offer this, NONE!! This is something people forget to mention, but this is very valuableDelphi, Eiffel and Common Lisp.
Oct 05 2021
On 10/4/21 6:23 AM, Paul Backus wrote:In ["Rust and Other Interesting Things"][1], Bryan Cantrill talks about the importance of a programming language's *values*[...][1]: https://www.youtube.com/watch?v=2wZ1pCpJUIMThis thread is on-topic. :) As Mike Parker hinted in his report on the past DLang Foundation meeting, I talked to a professional (in a non-professional setting) who works for a branding agency. She told me that the branding process can involve the following steps: 1. Competitor audit - What do e.g. C++ and Rust say about themselves? What do we say? How do we speak? What do we talk about? How do we look? 2. Immersion meetings - What is the difference of D lang? What features are prominent? How is it superior to its competition? What does the audience expect from D lang and the competition? How does or can D lang respond to these expectations? 3. Positioning discussion - What is the purpose of D lang? Who does it target? What does it offer them? The strategy must be determined according to this. 4. Brand identity - messaging (What points should be brought forward when talking about D lang?), voice (How are we going to speak when talking about D lang? Professional? Friendly? Comedic? Expertly? etc), visual (How should D lang be seen? logo, colors, font, images, etc) Apparently, in general, the first 3 steps take a month and the fourth step takes 2-3 months. Everybody is like us: It is hard to identify what a product actually is and how it can be branded most effectively. Seeing how involved branding is, to be able to get to a level with our (supposed ;) ) competitors, I think we must work with professionals. We programmers are smart people and I appreciate our efforts to come up with tag lines, logos, web site designs, etc. but our smarts do not necessarily work well for branding. So, I appreciate this timely thread very much, which should help answer the questions above. Ali
Oct 04 2021
On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:I thought it might be fun to ask the D community: **which of the above values do you think are the most important to D? Choose no more than 5, and reply with your answer!**```d enum msg = "CkkgdGhpbmsgaXQncyAoaW4gbm8gcGFydGljdWxhciBvcmRlcikgY29tcG9zYWJpbGl0eSwgaW50ZX" ~"JvcGVyYWJpbGl0eSwgc2FmZXR5CmFuZCBwZXJmb3JtYW5jZS4gU2FmZXR5IGFuZCBwZXJmb3JtYW5" ~"jZSBhcmUgaW1wb3J0YW50IHRoZSBzYW1lIHdheSBhcyB0aGV5IGFyZSB0bwpSdXN0LCBidXQgY29t" ~"cG9zYWJpbGl0eSBhbmQgaW50ZXJvcGVyYWJpbGl0eSBhcmUgd2hlcmUgd2UgZGlmZmVyIGZyb20gd" ~"Ghlbi4KCkQgdHJpZXMgdG8gYmUgY29tcGF0aWJsZSB3aXRoIGFzIG1hbnkgbGFuZ3VhZ2VzIGFzIH" ~"Bvc3NpYmxlLCBoZW5jZQppbnRlcm9wZXJhYmlsaXR5LiBJbiBBdGlsYSdzIHdvcmRzLCBpdCBhaW1" ~"zIHRvIGJlIHRoZSBkZWZhdWx0IGltcGxlbWVudGF0aW9uCmxhbmd1YWdlLiBJdCBhbHNvIHRyaWVz" ~"IHRvIGF2b2lkIHJlaW52ZW50aW5nIHRoZSBzeW50YXggbW9yZSB0aGFuIFJ1c3QgZG9lcy4KCkFuZ" ~"CBJIHRoaW5rIEQgYWxzbyBmb2xsb3dzIHRoZSBVbml4IHBoaWxvc29waHkgb2YgY29tcG9zYWJpbG" ~"l0eSB0byBhIGhpZ2gKZGVncmVlLiBJdCdzIGRlc2lnbmVkIGVxdWFsbHkgZm9yIHN5c3RlbXMgcHJ" ~"vZ3JhbW1pbmcsIGFwcGxpY2F0aW9uIHByb2dyYW1taW5nCmFuZCBzY3JpcHRpbmcsIGFuZCBpcyB0" ~"b3RhbGx5IG11bHRpLXBhcmFkaWdtLgo=" ; void main() { import std.stdio; import std.base64; writeln(cast(char[])Base64.decode(msg)); } ```
Oct 04 2021
On 10/4/21 1:24 PM, Dukc wrote:On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:[snip]I thought it might be fun to ask the D community: **which of the above values do you think are the most important to D? Choose no more than 5, and reply with your answer!**```d```This message was a reference type containing protected values.
Oct 04 2021
On Monday, 4 October 2021 at 20:42:06 UTC, David Gileadi wrote:This message was a reference type containing protected values.Huh, what did you try to do? I tested the snippet before posting and for me, it worked.
Oct 05 2021
On 10/5/21 6:17 AM, Dukc wrote:On Monday, 4 October 2021 at 20:42:06 UTC, David Gileadi wrote:Sorry, it was my poor attempt at wordplay. Please ignore.This message was a reference type containing protected values.Huh, what did you try to do? I tested the snippet before posting and for me, it worked.
Oct 05 2021
On Tuesday, 5 October 2021 at 14:31:15 UTC, David Gileadi wrote:On 10/5/21 6:17 AM, Dukc wrote:I got the joke anyway 😅On Monday, 4 October 2021 at 20:42:06 UTC, David Gileadi wrote:Sorry, it was my poor attempt at wordplay. Please ignore.This message was a reference type containing protected values.Huh, what did you try to do? I tested the snippet before posting and for me, it worked.
Oct 05 2021
On 10/4/2021 6:23 AM, Paul Backus wrote:One slide in his presentation contains a list of things that a programming language might value: Approachability Integrity Robustness Availability Maintainability Safety Compatibility Measurability Security Composability Operability Simplicity Debuggability Performance Stability Expressiveness Portability Thoroughness Extensibility Resiliency Transparency Interoperability Rigor VelocityInterestingly, left off is one thing that D does very well at: plasticity. What do I mean by that? I've been developing code for a loooong time. I've noticed a couple long term trends with C and C++ code. One is brittleness. This manifests itself in the strange characteristic that no matter how many years I work on a piece of code, the very first organization of it and the structure of it never fundamentally changes. Oh, I endlessly tweak it and optimize it and enhance it, but it's still the original design under the hood. I.e. it is brittle. With D code, however, I've found it to be far easier to change the design. Optimization becomes not so much sweating the details, but lowered barriers to trying out different designs to see what works better. I did this extensively on the Warp preprocessor project. I discovered a key component of this is D's use of . instead of ->. One can easily test drive with classes, structs, pointers, and values, interchanging them as one would try on a shirt. It's such a frackin' nuisance to do that in C and C++, one just doesn't bother. This is plasticity, the opposite of brittleness. What are your experiences with this?
Oct 04 2021
On Monday, 4 October 2021 at 22:15:33 UTC, Walter Bright wrote:What are your experiences with this?I find code that does Design by Introspection tends to be very resilient to additions, modifications, and removals. For example, I have a library that makes heavy use of introspection, and I completely changed the way the introspection was being handled without having to touch the way the user code was designed. This was done without breakage (well... there was one break due to a language limitation), and with very minor behavioral differences. It was definitely quite magical. Adding things is as simple as making a new UDA, slapping in some glue code for the introspect layer, and then applying it where relevant. Modifications don't really break anything unless the UDA itself is changed. Removals technically don't break much since the user part of the code is just ignored and non-functional now. DbI can be pretty awesome.
Oct 04 2021
On Monday, 4 October 2021 at 23:01:31 UTC, SealabJaster wrote:On Monday, 4 October 2021 at 22:15:33 UTC, Walter Bright wrote:Can you please list any resources on DbI? I've been finding it pretty hard to grasp, and I only managed to find a few videos by Andrei on the subject. Even the d-idioms website doesn't have much. Any text sources would be really appreciated. Thank you for reading!What are your experiences with this?I find code that does Design by Introspection tends to be very resilient to additions, modifications, and removals. For example, I have a library that makes heavy use of introspection, and I completely changed the way the introspection was being handled without having to touch the way the user code was designed. This was done without breakage (well... there was one break due to a language limitation), and with very minor behavioral differences. It was definitely quite magical. Adding things is as simple as making a new UDA, slapping in some glue code for the introspect layer, and then applying it where relevant. Modifications don't really break anything unless the UDA itself is changed. Removals technically don't break much since the user part of the code is just ignored and non-functional now. DbI can be pretty awesome.
Oct 04 2021
On Monday, 4 October 2021 at 23:10:27 UTC, Tejas wrote:...I'm not actually too sure about anything specifically on DbI. Anything to do with using UDAs would be pretty close: 1. http://ddili.org/ders/d.en/uda.html 2. https://bradley.chatha.dev/blog/dlang-json-serialiser-5 (is part of a multi-part blog series, so might be hard to follow by itself) You've motivated me to add a bit about DbI onto my upcoming DConf talk (assuming it's not too late for me to make changes)! So hopefully that'll be a bit of help as well. Generally a pairing of static if, static foreach, and anything to do with __traits is what I'd define as DbI.
Oct 04 2021
On Monday, 4 October 2021 at 23:56:41 UTC, SealabJaster wrote:On Monday, 4 October 2021 at 23:10:27 UTC, Tejas wrote:That's okay, parts 1-4 a literally a click away :D Thank you very much for sharing a real code-base that is also explained in a somewhat tutorial manner!...I'm not actually too sure about anything specifically on DbI. Anything to do with using UDAs would be pretty close: 1. http://ddili.org/ders/d.en/uda.html 2. https://bradley.chatha.dev/blog/dlang-json-serialiser-5 (is part of a multi-part blog series, so might be hard to follow by itself) You've motivated me to add a bit about DbI onto my upcoming DConf talk (assuming it's not too late for me to make changes)! So hopefully that'll be a bit of help as well. Generally a pairing of static if, static foreach, and anything to do with __traits is what I'd define as DbI.
Oct 04 2021
On Monday, 4 October 2021 at 23:10:27 UTC, Tejas wrote:Can you please list any resources on DbI? I've been finding it pretty hard to grasp, and I only managed to find a few videos by Andrei on the subject. Even the d-idioms website doesn't have much. Any text sources would be really appreciated. Thank you for reading!Design by introspection is when you have templated code "customize" itself based on the specific type(s) it's instantiated with. One place DbI is used a lot is in `std.range`. For example, here's how `std.range`'s documentation describes the return value of `retro`:Type: auto A bidirectional range with length if r also provides a length. Or, if r is a random access range, then the return value will be random access as well.Source: https://phobos.dpldocs.info/std.range.retro.html#returns Notice those "if" clauses. The return value has a `.length` property **if** the original range, `r`, has a `.length` property. That's DbI. How is it done? Internally, `retro` uses introspection features like `__traits` and `is()` expressions to check what properties `r` has, and uses `static if` to customize its own implementation based on the result of those checks.
Oct 04 2021
On Tuesday, 5 October 2021 at 00:11:29 UTC, Paul Backus wrote:On Monday, 4 October 2021 at 23:10:27 UTC, Tejas wrote:Is that seriously all there is to it? I see Andrei saying in his talks that `static if` doubles the design space covered, that DbI can tackle combinatorial explosion. Can DbI really help with software that gets complex exponentially? I guess a couple case studies will be nice. I've been putting it off, but maybe it's time I ignore the "experimental" smell of `checkedint` and `allocator` and actually study the underlying code. I'm genuinely having trouble comprehending how a bunch of compile time queries help reduce the complexity of software constructs exponentially... (maybe because I'm conflating it with **lines of code** metric, thinking that DbI will somehow make a 100_000 line program writable in a couple thousand lines)Can you please list any resources on DbI? I've been finding it pretty hard to grasp, and I only managed to find a few videos by Andrei on the subject. Even the d-idioms website doesn't have much. Any text sources would be really appreciated. Thank you for reading!Design by introspection is when you have templated code "customize" itself based on the specific type(s) it's instantiated with. One place DbI is used a lot is in `std.range`. For example, here's how `std.range`'s documentation describes the return value of `retro`:Type: auto A bidirectional range with length if r also provides a length. Or, if r is a random access range, then the return value will be random access as well.Source: https://phobos.dpldocs.info/std.range.retro.html#returns Notice those "if" clauses. The return value has a `.length` property **if** the original range, `r`, has a `.length` property. That's DbI. How is it done? Internally, `retro` uses introspection features like `__traits` and `is()` expressions to check what properties `r` has, and uses `static if` to customize its own implementation based on the result of those checks.
Oct 04 2021
On Tuesday, 5 October 2021 at 00:51:26 UTC, Tejas wrote:On Tuesday, 5 October 2021 at 00:11:29 UTC, Paul Backus wrote:Whenever you write a `static if` statement, you end up with two possible versions of the code: one where the condition is true, and one where it's false. It follows that if you have N `static if` statements in your program, then you have 2^N possible versions of the code--so the number of versions increases exponentially with respect to the number of `static if` statements. If you assume that "number of `static if` statements" is proportional to "number of lines of code", then you can make the claim that DbI allows you to write programs in O(N) lines that would otherwise take O(2^N) lines. Of course, this is not really true in practice. In languages that don't support DbI, what actually happens is that you do not write all 2^N customized versions of the code. Instead, you give up on having individual customized versions for each use-case and write a single version based on some lowest-common-denominator abstraction. What you really lose here are the benefits to performance and expressiveness that come from having individually-customized versions of your code.Notice those "if" clauses. The return value has a `.length` property **if** the original range, `r`, has a `.length` property. That's DbI. How is it done? Internally, `retro` uses introspection features like `__traits` and `is()` expressions to check what properties `r` has, and uses `static if` to customize its own implementation based on the result of those checks.Is that seriously all there is to it? I see Andrei saying in his talks that `static if` doubles the design space covered, that DbI can tackle combinatorial explosion. Can DbI really help with software that gets complex exponentially?
Oct 04 2021
On Tuesday, 5 October 2021 at 01:33:45 UTC, Paul Backus wrote:On Tuesday, 5 October 2021 at 00:51:26 UTC, Tejas wrote:So the key is getting expressiveness and performance while maintaining a degree of conciseness. This thread has been very useful for me, thank you, and everyone who has answered me :D[...]Whenever you write a `static if` statement, you end up with two possible versions of the code: one where the condition is true, and one where it's false. It follows that if you have N `static if` statements in your program, then you have 2^N possible versions of the code--so the number of versions increases exponentially with respect to the number of `static if` statements. [...]
Oct 04 2021
On Tuesday, 5 October 2021 at 01:33:45 UTC, Paul Backus wrote:Of course, this is not really true in practice. In languages that don't support DbI, what actually happens is that you do not write all 2^N customized versions of the code. Instead, you give up on having individual customized versions for each use-case and write a single version based on some lowest-common-denominator abstraction. What you really lose here are the benefits to performance and expressiveness that come from having individually-customized versions of your code.What really happens in other languages is either proliferation of code (copy/paste) or branching at runtime (if cascades, booleans or switch/case). The D way may end up adding more code, but code with less branching.
Oct 05 2021
On Tuesday, 5 October 2021 at 14:46:16 UTC, Patrick Schluter wrote:On Tuesday, 5 October 2021 at 01:33:45 UTC, Paul Backus wrote:a thing I notice from the C code where I work is that there is a lot of copy paste when things are done in a hurry - a thing that imo happens a lot less with D because of its wide set of compile time features.Of course, this is not really true in practice. In languages that don't support DbI, what actually happens is that you do not write all 2^N customized versions of the code. Instead, you give up on having individual customized versions for each use-case and write a single version based on some lowest-common-denominator abstraction. What you really lose here are the benefits to performance and expressiveness that come from having individually-customized versions of your code.What really happens in other languages is either proliferation of code (copy/paste) or branching at runtime (if cascades, booleans or switch/case). The D way may end up adding more code, but code with less branching.
Oct 05 2021
On Wed, Oct 06, 2021 at 05:47:43AM +0000, WebFreak001 via Digitalmars-d wrote: [...]a thing I notice from the C code where I work is that there is a lot of copy paste when things are done in a hurry - a thing that imo happens a lot less with D because of its wide set of compile time features.I also noticed from the C code at my job that there's a lot of copy-n-paste. Some of the worst instances include buggy static functions that are copied all over the place, with the bug fixed in some copies but not the others. IIRC there was even one instance where two different bugfixes were applied to two different copies of the same function, each causing it to behave differently from the other copy. It's an utter maintenance nightmare. This is why I love the way D lets you eliminate duplicate code and other such boilerplate. Repetition in code is, as a rule, a code smell that inevitably leads to later maintenance problems. T -- Having a smoking section in a restaurant is like having a peeing section in a swimming pool. -- Edward Burr
Oct 07 2021
On 10/4/21 5:11 PM, Paul Backus wrote:One place DbI is used a lot is in `std.range`.Even before hearing the term Design by Introspection, I was showing Phobos algorithms to explain 'static if's usefulness when I was presenting D to mostly C++ programmers. We imagine iota, map, etc. algorithms returning result types implementing the InputRange interface. And it makes sense: iota generates elements in order, map produces results in order, etc. However, because 'iota' is capable of implementing opIndex, map can do so as well. So, the whole range object is usable as a RandomAccessRange: import std.range; import std.algorithm; void main() { auto r = 10.iota.map!(i => i * 2); if (r[$/2] > r[0]) { // This works! // ... } } Ali P.S. Yes, iota provides opDollar as well, and so can map, etc.
Oct 04 2021
On Mon, Oct 04, 2021 at 11:10:27PM +0000, Tejas via Digitalmars-d wrote: [...]Can you please list any resources on DbI? I've been finding it pretty hard to grasp, and I only managed to find a few videos by Andrei on the subject.[...] The basic idea is very simple (but the results are powerful indeed). Basically, in traditional code, when a function takes a parameter, say, it specifies exactly what the type T of the parameter must be (int, float, some struct, etc.). In the function body, it makes use of the implementation details of this type in order to perform operations on the data. auto myFunc(T data) { ... } Experience shows, however, that often the function doesn't actually depend on *all* the details of the type T. Perhaps it uses only a small subset of its fields/methods. For example, the function may only need to use .front and .empty. So there's no reason for the function to demand that incoming arguments must be of a fixed type T; T can really be *any* type that happens to have a .front and .empty with the expected semantics. So we move from a normal (non-template) function to a template function: auto myFunc(T)(T data) { ... // make use of .front, .empty here } So far so good, we all know what template functions are. But DbI takes this one step further: suppose myFunc doesn't actually need to use .empty. Maybe there's a different way to do what it wants without using .empty, but it uses .empty because of efficiency (or whatever other reason). Still, since it's not strictly necessary, why make the function depend on it? It would be nice to be able to pass types to myFunc that don't have .empty, so that it can perform its magic (albeit somewhat less efficiently/whatever). So what we do instead is to use `static if` to inspect the incoming type T, and adapt ourselves accordingly: auto myFunc(T)(T data) { static if (... /* T has .empty) { ... // make use of .front, .empty here } else { ... // alternative implementation that doesn't use .empty } } Voila! Now myFunc can take both types that have .front and .empty, and types that only have .front. (Note also that this doesn't have to be limited to the presence/absence of a field. It can be any attribute of T inspectable at compile-time. You can have static if blocks to switch between implementations based on the size of a type, for example to make decisions about how to best allocate storage for a large number of its instances, say. Or, the favorite among D users, make decisions based on some UDA that you attach to the type in order to change how the function processes it.) This may seem trivial, but it has powerful consequences. By making myFunc independent of the existence of .empty, we've increased its scope of applicability to a wider set of types. Each static if we introduce more-or-less doubles the set of types for which the function is applicable. Instead of writing one function for types that have .front and .empty and another function for types that have only .front, we can process both according to the same logic. Instead of demanding the caller of the function to supply us with a type fulfilling requirements A, B, C, we adapt ourselves to whatever type the caller may throw at us, making use of compile-time introspection to discover what the type can do and adapting ourselves accordingly. // An actual example I wrote myself: a serialization module I wrote for writing out objects into text form and reading it back later to reconstruct said objects. Instead of the traditional method of inserting a .serialize method into every struct and class (wayyyy too tedious, repetitious, and highly prone to bugs caused by human error), my code instead does this: void save(S,T)(S storage, T data) { static if (is(T == struct)) { ... // serialize structs here } else static if (is(T == class)) { ... // serialize structs here } else if (is(T == U[], U)) { ... // serialize arrays here } else if (is(T : int)) { ... // serialize int-like types here } ... // etc else static assert(0, "Can't serialize type " ~ T.stringof); } So, when I want to serialize a struct S, what do I do? S data; storage.save(data); When I want to serialize an int? int data; storage.save(data); When I want to serialize an array? S[] data; storage.save(data); Super-easy. Notice that I deliberately named my data `data`: that means if I ever decide to change the type of my data, I don't even need to edit the .save line; I just change the type of `data`, and .save Just Works(tm). It automatically adapts itself to whatever type is passed to it. No need to call a different function, pass a ton of flags, none of that fuss and muss. Just hand it a different type, and it Just Works(tm). But wait, there's more! What if I want to treat strings differently from other arrays? Easy, just add a static if block to .save that handles strings before it handles general arrays: void save(S,T)(S storage, T data) { static if ... ... else if (is(T == string)) { ... // special handling for strings here } else if (is(T == U[], U)) { ... // handle general arrays here } else ... } But what if I want a different serialization scheme for certain data types? E.g., if I have a struct MyStruct, and I don't want to serialize *all* fields, but want to exclude, say, fields that only store cached data that can be recomputed next time? Here's where UDAs come into play: I mark fields I don't want to save with a special UDA: struct DontSerialize {} struct MyStruct { int i; // save this float f; // save this too DontSerialize string s; // don't save this } void save(S,T)(S storage, T data) { ... static if (is(T == struct)) { foreach (field; allMembers!T) { // skip fields tagged with DontSerialize static if (!hasUDA!(mixin("data."~field), DontSerialize)) { ... // serialize here } } } ... } Notice how clean this is. In a traditional approach, I'd have to pass some kind of blacklist to .save, perhaps an AA of stuff I don't want to save, or some boolean flags, etc.. But with DbI, the API of .save remains exactly the same as before: MyStruct[] data; storage.save(data); // <--- exactly the same as before All I need to do is to tag the field in the definition of MyStruct -- no need to change code in all the places that pass MyStruct to .save, no need to change the API of .save (or, God forbid, add a new overload / different function just to handle this case), just add a new static if block to check for the UDA, and it Just Works. In other words, adding a new static if block to .save "teaches" it how to adapt to structs that contain fields that shouldn't be saved. Once thus taught, you can just hand it any type appropriately tagged with the UDA, and it automatically does the Right Thing(tm). No fuss, no muss, no extra parameters, no messy option flags, no massive refactoring of every callsite of .save, just a couple of lines of code change and we're done. There's so much more you could do to it. For example, another UDA for tagging types that should use a different serialization scheme (e.g., highly-compressible data that should be filtered through a compression algorithm). Another UDA that filters an array to exclude elements that don't need to be saved. Etc.. With every addition, .save becomes more and more powerful, yet its API remains exactly the same as before: storage.save(data); // <--- exactly the same as before Code that calls .save don't need to be touched just because some data type now needs different serialization behaviour. No massive refactorings needed, no proliferation of flags and other extraneous parameters to .save. Just tag the type definition, and we're good to go. This, my friend, is the power of DbI. This example, of course, only scratches the surface of what you can do with DbI, but I'll leave it up to you to explore the rest. :-D T -- Nearly all men can stand adversity, but if you want to test a man's character, give him power. -- Abraham Lincoln
Oct 04 2021
On Tuesday, 5 October 2021 at 01:11:22 UTC, H. S. Teoh wrote:On Mon, Oct 04, 2021 at 11:10:27PM +0000, Tejas via Digitalmars-d wrote: [...]... ... ... You're the absolute best, you know that? Thank you so much for taking the time and effort to write this, I'll be bookmarking this and reading it every single time I doubt my understanding of DbI. In fact, I think this even deserves a place in in p0nce's d-idioms page[...][...] The basic idea is very simple (but the results are powerful indeed). [...]
Oct 04 2021
On Tuesday, 5 October 2021 at 01:11:22 UTC, H. S. Teoh wrote:... This, my friend, is the power of DbI. This example, of course, only scratches the surface of what you can do with DbI, but I'll leave it up to you to explore the rest. :-DI'm not the OP but I'd like to say thank you very much for taking time and writing this, it gave me a wish to write some code and play with this idea. Matheus.
Oct 04 2021
On Tuesday, 5 October 2021 at 01:11:22 UTC, H. S. Teoh wrote:The basic idea is very simple (but the results are powerful indeed)....... `Good Article`,I have translated into Chinese,[link here](https://fqbqrr.blog.csdn.net/article/details/120612027)
Oct 04 2021
On Monday, 4 October 2021 at 23:10:27 UTC, Tejas wrote:Even the d-idioms website doesn't have much. Any text sources would be really appreciated. Thank you for reading!The construction of the allocator library in https://www.youtube.com/watch?v=LIb3L4vKZ7U is really quite the lesson. Also "Functional image processing in D": https://blog.cy.md/2014/03/21/functional-image-processing-in-d/ With all the good thing that _can_ be said about DbI, I don't think it is a defining feature of D. After using ae.utils.graphics for years, I turned 180° and now think generic programming typically get a few problems: - it's a bit remote from problem domains, meaning a bit less readable code, a bit harder to write, a bit longer to compile... in exchange for the expanded capabilities and genericity - the problem of having less specific identifiers - the problem of typically having poor information-hiding. Probably the idea was that the software artifact is so generic, it has to be made public. Leading to too much being public.
Oct 05 2021
On Tuesday, 5 October 2021 at 20:12:07 UTC, Guillaume Piolat wrote:On Monday, 4 October 2021 at 23:10:27 UTC, Tejas wrote:So apart from the plasticity that others mention, why do you feel D is better than the alternatives out there for your field of work? Why do you continue to walk the path less travelled when others enjoy the advantages of mainstream languages like better tooling and greater stability, ie, fewer/no breaking changes with each release(and disadvantages like various janky workarounds for backwards compatibility, deigns/ideological constraints, etc)?Even the d-idioms website doesn't have much. Any text sources would be really appreciated. Thank you for reading!The construction of the allocator library in https://www.youtube.com/watch?v=LIb3L4vKZ7U is really quite the lesson. Also "Functional image processing in D": https://blog.cy.md/2014/03/21/functional-image-processing-in-d/ With all the good thing that _can_ be said about DbI, I don't think it is a defining feature of D. After using ae.utils.graphics for years, I turned 180° and now think generic programming typically get a few problems: - it's a bit remote from problem domains, meaning a bit less readable code, a bit harder to write, a bit longer to compile... in exchange for the expanded capabilities and genericity - the problem of having less specific identifiers - the problem of typically having poor information-hiding. Probably the idea was that the software artifact is so generic, it has to be made public. Leading to too much being public.
Oct 06 2021
On Wednesday, 6 October 2021 at 23:26:14 UTC, Tejas wrote:So apart from the plasticity that others mention, why do you feel D is better than the alternatives out there for your field of work?My field is largely dominated by C++. So I'll talk largely about that "obvious" alternative, that is C++. I happen to have years of commercial experience in both. I feel qualified to have strong opinion in this case. So, what conclusion did I reach afters years of both C++ and D? First of all: - They are very different universe; you really do live in a different universe when full-time. The culture is completely different. Secondly: - D lets me do my best work. - C++ makes me very unlikely to do my best work.Why do you continue to walk the path less travelled when others enjoy the advantages of mainstream languages like better tooling and greater stability, ie, fewer/no breaking changes with each release(and disadvantages like various janky workarounds for backwards compatibility, deigns/ideological constraints, etc)?But that description does not characterize mainstream C++. It's not at all what you describe once in the trenches. In reality C++ doesn't compare favorably to D in pretty basic ways. Tools in C++ are not much better for me (cmake vs dub, what would you really prefer?), build times are usually worse, compilers are also kinda crashy, STL is a lot less usable than Phobos. Would you rather read C++ or D all day long? Honestly. Different, incompatible syntax to do things in different vendors. You absolutely do more backwards compatibility shenanigans in C++, if only because the standard advance so quickly, and the stdlib are made differently - at different stages of the newest standard. And C++ is also a bad learning investment for anyone, since you cannot learn C++ as fast as the Standard Comittee makes changes. D changes a lot less and you can learn it in 3x less time. Practionners then get the strangest Stockholm syndrom and take pride in knowing C++ minutiae like if it mattered. The real question is: why start a green C++ project today instead of D. Apart from: staffing, specific platforms, or legacy I don't think the positives outweight the negatives.
Oct 07 2021
On Thursday, 7 October 2021 at 13:29:34 UTC, Guillaume Piolat wrote:On Wednesday, 6 October 2021 at 23:26:14 UTC, Tejas wrote:Interesting. I'm on the fence on if I should pick up C++ again or not. But the sad truth is that there still is really not an alternative when it comes to embedded, especially not regarding functional safety :´( But, to use C++ for "normal" stuff seems just like torture. Why[...]My field is largely dominated by C++. So I'll talk largely about that "obvious" alternative, that is C++. [...]
Oct 07 2021
On Thursday, 7 October 2021 at 14:41:26 UTC, Imperatorn wrote:On Thursday, 7 October 2021 at 13:29:34 UTC, Guillaume Piolat wrote:Metal Shading Language, CUDA, working on LLVM or GCC internals, the Android or Windows stuff that only has C++ bindings available, Arduino, ARM mbed, high integrity computing standards like AUTOSAR, macOS drivers, game consoles SDKs, Swift, .NET and Java runtimes,... There are plenty of places where it would be nice to use something else, but C++ is the name of the game, and adding extra layers to debugging is not getting the buy-in from most folks.On Wednesday, 6 October 2021 at 23:26:14 UTC, Tejas wrote:Interesting. I'm on the fence on if I should pick up C++ again or not. But the sad truth is that there still is really not an alternative when it comes to embedded, especially not regarding functional safety :´( But, to use C++ for "normal" stuff seems just like torture. Why[...]My field is largely dominated by C++. So I'll talk largely about that "obvious" alternative, that is C++. [...]
Oct 07 2021
On Thursday, 7 October 2021 at 17:21:16 UTC, Paulo Pinto wrote:On Thursday, 7 October 2021 at 14:41:26 UTC, Imperatorn wrote:Yep, that's the unfortunate truth[...]Metal Shading Language, CUDA, working on LLVM or GCC internals, the Android or Windows stuff that only has C++ bindings available, Arduino, ARM mbed, high integrity computing standards like AUTOSAR, macOS drivers, game consoles SDKs, Swift, .NET and Java runtimes,... There are plenty of places where it would be nice to use something else, but C++ is the name of the game, and adding extra layers to debugging is not getting the buy-in from most folks.
Oct 07 2021
On Thursday, 7 October 2021 at 13:29:34 UTC, Guillaume Piolat wrote:First of all: - They are very different universe; you really do live in a different universe when full-time. The culture is completely different.Interesting! How do D and C++ cultures differ?Tools in C++ are not much better for me (cmake vs dub, what would you really prefer?), build times are usually worse, compilers are also kinda crashy, STL is a lot less usable than Phobos. Would you rather read C++ or D all day long? Honestly.Wow, are modern C++ compilers crashy *when compared to D*? I definitely agree that D compilers nowadays are more than stable enough for production, but do they really rival the most common C++ ones? And is this when using recent C++ features or also with older codebases?Different, incompatible syntax to do things in different vendors. You absolutely do more backwards compatibility shenanigans in C++, if only because the standard advance so quickly, and the stdlib are made differently - at different stages of the newest standard.To be fair this is probably because all the widely used D compilers have the same frontend. If SDC was in production too it would be a fairer comparison.And C++ is also a bad learning investment for anyone, since you cannot learn C++ as fast as the Standard Comittee makes changes. D changes a lot less and you can learn it in 3x less time. Practionners then get the strangest Stockholm syndrom and take pride in knowing C++ minutiae like if it mattered.More news for me, if you really mean that. C++ does add features fast for such an old language. But changing faster than D, considering they tend to keep the old features around where we deprecate them? Really?The real question is: why start a green C++ project today instead of D. Apart from: staffing, specific platforms, or legacy I don't think the positives outweight the negatives.I sign that one (to surprise of none I guess).
Oct 07 2021
On Thursday, 7 October 2021 at 20:12:49 UTC, Dukc wrote:Wow, are modern C++ compilers crashy *when compared to D*? I definitely agree that D compilers nowadays are more than stable enough for production, but do they really rival the most common C++ ones?LDC rivals clang of course. On what metric do you think it wouldn't? And if you have used C++ professionally, yes you stumble upon compiler bugs. I certainly have. And in that case there is often no nice bugtracker to file that bug. D having one front-end means that in practice you have less unknowns.More news for me, if you really mean that. C++ does add features fast for such an old language. But changing faster than D, considering they tend to keep the old features around where we deprecate them? Really?Yes really, it is very difficult to keep up with the C++ changes even if you were a full-time C++ programmer. And you need to since people start to use the new stuff when available. It is very likely that when the next standard comes out, you would have barely assimilated the one from 10 years ago. C++ needs a cast of "explainers" like Scott Meyers.
Oct 07 2021
On Thursday, 7 October 2021 at 22:07:13 UTC, Guillaume Piolat wrote:Yes really, it is very difficult to keep up with the C++ changes even if you were a full-time C++ programmer. And you need to since people start to use the new stuff when available. It is very likely that when the next standard comes out, you would have barely assimilated the one from 10 years ago. C++ needs a cast of "explainers" like Scott Meyers.I've given up on C++ unless it is embedded programming. C++ is still ok for embedded but since you don't use much from the standard library, it looks more like C++11 or before that, not much change with another words. I expect to use less C++ for embedded as time goes by as well. Many of the changes in "modern C++" are made for application programming and library improvements. The problem is that today if you are going to do application programming there are a myriad of better alternatives, D is one of them. The last application programming projects I worked on professionally with C++ have just been a pain. It was so obvious that despite all the "modern improvements", C++ cannot compete anymore. Also since there are dozens of ways to do the same thing in C++, the code becomes very inconsistent. The question is, should you invest a lot of time learning C++? Both yes and no. C++ and C is still lowest common denominator when it comes to APIs and FFIs. Learn C++ so that you understand moderate amount. Learning C++ to become a meta programming wizard would be a waste of time, for me at least. That would be huge investment of time that I don't think is worth it. Better alternatives exists.
Oct 07 2021
On Thursday, 7 October 2021 at 22:21:21 UTC, IGotD- wrote:On Thursday, 7 October 2021 at 22:07:13 UTC, Guillaume Piolat wrote:Chances of Rust taking over that segment? Also C++ is still used (and must be used??) for applications like photo and video editing s/w. C++?[...]I've given up on C++ unless it is embedded programming. C++ is still ok for embedded but since you don't use much from the standard library, it looks more like C++11 or before that, not much change with another words. [...]
Oct 08 2021
On Friday, 8 October 2021 at 11:00:59 UTC, Tejas wrote:Chances of Rust taking over that segment? Also C++ is still used (and must be used??) for applications like photo and video editing s/w. pf C++?Rust is already partially eating up the marketshare of C/C++. There is a big drive to enable Rust for Linux drivers for example. For low level programming, I find Rust annoying but some people might endure it. When it comes to applications, it is a mystery to me that C++ still is so popular. Probably mostly because there is an existing code base that companies don't want to rewrite. This is a great opportunity for D as the FFI is one of the best out there which enables a gradual migration. I'm not sure what the status is and if you get the same performance. For cross platform GUI application, there isn't an obvious choice. C++ with Qt is still a strong contender but it is becoming proprietary. Let's not forget web applications, when performance is not required web applications do a good enough job at the same time becoming totally platform independent. runs just as well as any C++ program.
Oct 08 2021
On Friday, 8 October 2021 at 12:46:33 UTC, IGotD- wrote:I'm not sure what the status is and if you get the same performance.of whether that's Windows, Linux etc. .NET Core (Or as it's now .NET 5) was really a game changer for
Oct 08 2021
On Friday, 8 October 2021 at 12:46:33 UTC, IGotD- wrote:On Friday, 8 October 2021 at 11:00:59 UTC, Tejas wrote:Linux and armhf[...]Rust is already partially eating up the marketshare of C/C++. There is a big drive to enable Rust for Linux drivers for example. For low level programming, I find Rust annoying but some people might endure it. [...]
Oct 08 2021
On Friday, 8 October 2021 at 18:57:55 UTC, Imperatorn wrote:Linux and armhfplatform development looks like. 1. You are making a free program that is available without charge for anyone. What are the licensing terms? 2. You are making a proprietary software which you charge money for. What are the licensing terms? Of course there are variants of this, but just to make it easier.
Oct 08 2021
On Friday, 8 October 2021 at 19:14:21 UTC, IGotD- wrote:On Friday, 8 October 2021 at 18:57:55 UTC, Imperatorn wrote:https://dotnet.microsoft.com/platform/freeLinux and armhfplatform development looks like. 1. You are making a free program that is available without charge for anyone. What are the licensing terms? 2. You are making a proprietary software which you charge money for. What are the licensing terms? Of course there are variants of this, but just to make it easier.
Oct 08 2021
should compare D is with (actually 3) Go/Rust/Zig compiles to IL and requires a massive runtime the graveyard of old and irrelevant tech
Oct 08 2021
On Saturday, 9 October 2021 at 00:23:00 UTC, russhy wrote:should compare D is with
Oct 08 2021
On Saturday, 9 October 2021 at 00:30:21 UTC, Adam Ruppe wrote:On Saturday, 9 October 2021 at 00:23:00 UTC, russhy wrote:If it had a competing GC, i'd say yes, but that's not the case I personally see D as best suited to be a more fun C++should compare D is with
Oct 08 2021
On Saturday, 9 October 2021 at 00:30:21 UTC, Adam Ruppe wrote:its metaprogramming capabilities, while once competitive, are now pretty unimpressive. The programming language state-of-the-art has come a long way in the last 20 years (even if most people are still using old tech.) The D language's CFTE is really THE game changer. I know of nothing else like it, and I could make some So I'm using D for some new projects. Of course, it has some other pretty innovative things too. For example, the scope(exit) construct. That's soooo much better than needing to enclose things in layer after layer of try-catch blocks. Other languages should all be copying this construct. developers who want to be more on the cutting edge.
Oct 08 2021
On Saturday, 9 October 2021 at 00:59:42 UTC, Greg Strong wrote:On Saturday, 9 October 2021 at 00:30:21 UTC, Adam Ruppe wrote:I still find Roslyn compiler plugins and the code generators quite good. You can simulate scope(exit) with an helper struct. ```csharp using System; #nullable enable // ensure this is a stack only struct ref struct ScopeExit { public ScopeExit(Action cleaner) { this.cleaner = cleaner; } public void Dispose() { try { cleaner(); } catch { // maybe do something interesting here } } private Action cleaner; } public class Example { public static void Main() { using var netSocket = new ScopeExit(() => { /* clean somethig */}); } } ``` Naturally D's scope(exist) is cleaner to write.But its metaprogramming capabilities, while once competitive, are now pretty unimpressive. The programming language state-of-the-art has come a long way in the last 20 years (even if most people are still using old tech.) The D language's CFTE is really THE game changer. I know of nothing else like base... So I'm using D for some new projects. Of course, it has some other pretty innovative things too. For example, the scope(exit) construct. That's soooo much better than needing to enclose things in layer after layer of try-catch blocks. Other languages should all be copying this construct. developers who want to be more on the cutting edge.
Oct 08 2021
On Saturday, 9 October 2021 at 06:50:19 UTC, Paulo Pinto wrote:On Saturday, 9 October 2021 at 00:59:42 UTC, Greg Strong wrote:0.5% would do ref struct and 0.1% would try to scope guard something, but nice experiment ofc 💕[...]I still find Roslyn compiler plugins and the code generators quite good. You can simulate scope(exit) with an helper struct. ```csharp using System; #nullable enable // ensure this is a stack only struct ref struct ScopeExit { public ScopeExit(Action cleaner) { this.cleaner = cleaner; } public void Dispose() { try { cleaner(); } catch { // maybe do something interesting here } } private Action cleaner; } public class Example { public static void Main() { using var netSocket = new ScopeExit(() => { /* clean somethig */}); } } ``` Naturally D's scope(exist) is cleaner to write.
Oct 09 2021
On Saturday, 9 October 2021 at 07:31:02 UTC, Imperatorn wrote:On Saturday, 9 October 2021 at 06:50:19 UTC, Paulo Pinto wrote:Sure when D's ecosystem catches up.[...]0.5% would do ref struct and 0.1% would try to scope guard something, but nice experiment ofc 💕
Oct 09 2021
On Saturday, 9 October 2021 at 12:11:51 UTC, Paulo Pinto wrote:On Saturday, 9 October 2021 at 07:31:02 UTC, Imperatorn wrote:Soon (tm) *dreaming* hypocriteOn Saturday, 9 October 2021 at 06:50:19 UTC, Paulo Pinto wrote:Sure when D's ecosystem catches up.[...]them 0.5% would do ref struct and 0.1% would try to scope guard something, but nice experiment ofc 💕
Oct 09 2021
On Saturday, 9 October 2021 at 12:11:51 UTC, Paulo Pinto wrote:Sure when D's ecosystem catches up.It'd definitely be a nice surprise if the leadership announced some sort of plan of action on tackling this issue, because without structured guidance I don't see this being possible. e.g. "What we need: * de-facto standard event loop * de-facto standard web server * de-facto standard json library * de-facto standard yaml library * de-facto standard logging library * de-facto standard database abstraction * de-facto standard whatever We'll do this by creating a list of requirements these libraries should meet, yada yada. We'll setup/use an official github org to organise these under, so they're not just random repos with random owners yada yada. Maybe even give them simple names on dub, literally "yaml", or "eventloop". The leadership will work together with the community to yada yada. " I'm obviously a very naive person, but would something like the above even be feasible, if useful at all? Because at the moment all I see is: "Person A ports/writes a library/binding. 1 year later it has 3 total downloads and is completely dead." "Person B does the exact same thing, and suffers the exact same fate". I wonder what it is about D that makes such coordination seemingly so difficult. Because when we used to have the Vision documents, it'd include things like "Get a new std.json library with X Y Z features", but they never came to fruition. It was more like a wishlist rather than a plan of action.
Oct 09 2021
On Saturday, 9 October 2021 at 20:42:25 UTC, SealabJaster wrote:...I guess a point I wanted to drive home is that these would be *official* things, not community-led things. These would be a core part of D's ecosystem rather than a hobby project one or two people have control over. This is definitely more difficult when D is almost purely volunteer based, and I'm sure there's a bunch more issues I wouldn't even be able to think of on my own.
Oct 09 2021
On Saturday, 9 October 2021 at 20:42:25 UTC, SealabJaster wrote:On Saturday, 9 October 2021 at 12:11:51 UTC, Paulo Pinto wrote:Agreed. Would be nice if you could streamline stuff a bit more[...]It'd definitely be a nice surprise if the leadership announced some sort of plan of action on tackling this issue, because without structured guidance I don't see this being possible. [...]
Oct 09 2021
On Saturday, 9 October 2021 at 06:50:19 UTC, Paulo Pinto wrote:You can simulate scope(exit) with an helper struct. [snip] Naturally D's scope(exist) is cleaner to write.public struct Ui { //... } // elsewhere abstract class Panel { // ... public Ui[] uiState; // ... } ``` The story behind that array is that I wanted a reference to the struct. Later on I came up with a less hackish way to achieve the same: //Intended for the same as C standard library div_t: result of division. public struct DivInt { public int quot; public int rem; } public class Ref<Struct> { public Struct value; public Ref(){} public Ref(Struct val){value = val;} } ``` Other examples of my programming: public static class Utility { //Because Debug.Assert message does not pop up on web page [System.Diagnostics.Conditional("DEBUG")] public static void Assert (bool condition) { Assert(condition, "Program in illegal state. Exiting."); } [System.Diagnostics.Conditional("DEBUG")] public static void Assert (bool condition, string message) { if (!condition) { Window.Alert(message); throw new InvalidOperationException(); } } public static void Swap<T>(ref T a, ref T b) { var temp = a; a = b; b = temp; } //don't use to add many elements sequentially in a loop, as that's inefficient. public static void Append<T>(ref T[] array, T what) { var oldLength = array.Length; Array.Resize(ref array, oldLength + 1); array[oldLength] = what; } //always rounds down, also when negative. public static DivInt Div(this int dividee, int divisor) { int quot; int rem; // Could this be assigned directly to the result value? quot = Math.DivRem(dividee, divisor, out rem); if(rem < 0) { quot--; rem += divisor; } return new DivInt{quot = quot, rem = rem}; } public static void Each<T>(this IEnumerable<T> range, Action<T> todo) { foreach(T el in range) todo(el); } public static IEnumerable<Sequence<T, int>> Enumerate<T>(this IEnumerable<T> range, int startValue) { return range.Zip(Enumerable.Range(startValue, int.MaxValue), (x, y) => new Sequence<T, int>(x, y)); } public static IEnumerable<Sequence<T, int>> Enumerate<T>(this IEnumerable<T> range) { return range.Enumerate(0); } } ``` My way of serializing and deserializing data to/from files would probably get red pen marks from fairly much everything. Representive deserialization here, struct data is commented in real life but not here because didn't bother to translate: public struct PillarInstallation { public Slab pillar; public Vector3D gap; public float angle; public Ref<StoneCutType>[] sideCutTypes // other member functions... public static PillarInstallation Deserialize ( byte[] from, int fromI, YhkVersion yhkVersion, int pillarI, Dictionary<string, int> textureChecker ) { int fromIAtStart = fromI; PillarInstallation result = new PillarInstallation(); result.pillar = Slab.Deserialize(from, fromI, textureChecker); fromI += Slab.serializedSize; result.gap = Vector3D.Deserialize(from, fromI); fromI += Vector3D.serializedSize; if (yhkVersion.Encompasses(new YhkVersion(8))) { result.angle = Utility.DeserializeFloat(from, fromI); fromI += 4; } else result.angle = 0; result.sideCutTypes = new Ref<StoneCutType>[2]; if (yhkVersion.Encompasses(new YhkVersion(12))) { for(int i=0; i<result.sideCutTypes.Length; i++) if(from[fromI+i]!=255) { var refVar = new Ref<StoneCutType>(); refVar.value = (StoneCutType)from[fromI+i]; result.sideCutTypes[i] = refVar; } } else { bool interfaceSawed = Utility.DeserializeInt(from, fromI) % 2 > 0; if (interfaceSawed) { var refVar = new Ref<StoneCutType>(StoneCutType.sawed); result.sideCutTypes[pillarI^1] = refVar; } } fromI += 4; Utility.Assert(fromIAtStart + GetSerializedSize(yhkVersion) == fromI, "read " + (fromI - fromIAtStart) + " bytes, should have read " + GetSerializedSize(yhkVersion)); return result; } } ```
Oct 10 2021
On Sunday, 10 October 2021 at 13:13:21 UTC, Dukc wrote:compiler"but" intended, not "put".
Oct 10 2021
On Saturday, 9 October 2021 at 00:59:42 UTC, Greg Strong wrote:On Saturday, 9 October 2021 at 00:30:21 UTC, Adam Ruppe wrote:This is kinda where I'm at atm. The *only* thing holding me back is the ecosystem. If we find a bug in D, we can probably fix it. But, if we don't find a library, the cost of creating it might be too big 😢 Imo D is mature enough now. It's battle tested. It's flexible etc. Has great metaprogramming. The language itself doesn't need much change apart from testing what exists even more, especially since we're soon at 2.1 😱 Aim for stability and robustness. Then focus on ecosystem. I come in peace, I thinkBut its metaprogramming capabilities, while once competitive, are now pretty unimpressive. The programming language state-of-the-art has come a long way in the last 20 years (even if most people are still using old tech.) The D language's CFTE is really THE game changer. I know of nothing else like base... So I'm using D for some new projects. Of course, it has some other pretty innovative things too. For example, the scope(exit) construct. That's soooo much better than needing to enclose things in layer after layer of try-catch blocks. Other languages should all be copying this construct. developers who want to be more on the cutting edge.
Oct 09 2021
On Saturday, 9 October 2021 at 07:38:01 UTC, Imperatorn wrote:Imo D is mature enough now. It's battle tested. It's flexible etc.That's where I think there are room for improvements. D is not flexible when it comes to choose memory management type because of lack of fat pointers. The shared memory model is a disaster. D is good but it has a few serious warts.
Oct 09 2021
On Saturday, 9 October 2021 at 08:47:10 UTC, IGotD- wrote:On Saturday, 9 October 2021 at 07:38:01 UTC, Imperatorn wrote:Agreed, but here I'm talking about the language aspect. There are some quirks - yes - but are those *more* important than ecosystem? If you *had* to choose? Ideally one would want a 100% complete foundation before expanding the ecosystem, I totally agree. But if I would be forced to choose with a gun to my head, I would say the ecosystem is where it's at. And to build a great ecosystem you need people. And to get people you need some selling points and marketing etc. Otherwise, how would people even know it exists? https://www.sciencedirect.com/science/article/pii/S0950584921001051 I've talked to various devs and like none of them have even heard of D, but when I show it the reaction is often like "hmm, that actually looks kinda nice".Imo D is mature enough now. It's battle tested. It's flexible etc.That's where I think there are room for improvements. D is not flexible when it comes to choose memory management type because of lack of fat pointers. The shared memory model is a disaster. D is good but it has a few serious warts.
Oct 09 2021
On Saturday, 9 October 2021 at 00:23:00 UTC, russhy wrote:should compare D is with (actually 3) Go/Rust/Zig it compiles to IL and requires a massive runtime the graveyard of old and irrelevant techMostly thinking about the language itself, syntax
Oct 08 2021
On Saturday, 9 October 2021 at 00:23:00 UTC, russhy wrote:should compare D is with (actually 3) Go/Rust/Zig it compiles to IL and requires a massive runtime the graveyard of old and irrelevant techSo much disinformation. https://docs.microsoft.com/en-us/windows/uwp/dotnet-native/ https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator https://github.com/dotnet/designs/blob/main/accepted/2020/form-factors.md#native-aot-form-factors https://docs.microsoft.com/en-us/xamarin/mac/internals/aot https://docs.unity3d.com/Manual/IL2CPP.html Running on production embedded hardware, https://www.wildernesslabs.co Apparently the majority of the games running in that Nintendo toy, that has broken all sale records, happen to use Unity in about 30% of their titles. https://www.kelltontech.com/kellton-tech-blog/reasons-develop-nintendo-switch-games-in-unity-game-engine Another graveyard irrelevant technology that besides Nintendo, is the tier 1 for Sony, Google and Microsoft gaming systems and AR/VR platforms, alongside Unreal. Looks pretty much alive to me. D also compiles to LDC bitcode and GCC gimple, and has a runtime. Should we also consider it not a systems language then? Don't let the hatred and lack of knowledge for other stacks cloud your judgement. It steers people away from D when false statements are being done about the ecosystems they know quite well, turning on their defences and thus stop listening on what D is actually supposed to be better on.
Oct 09 2021
On Saturday, 9 October 2021 at 07:13:38 UTC, Paulo Pinto wrote:On Saturday, 9 October 2021 at 00:23:00 UTC, russhy wrote:vibe-d and hunt helped compete with asp.net and spring, it's a known fact, the GC helps D web servers handle terabytes of heap memory and millions of transactions per seconds, also a known fact.. it also helped compete with the simplicity of go net/http, a very known fact, obviously you are looking at the past, when you want to be relevant tomorrow, you look forward there is not JIT and no low latency GC, you'll be forever a worst and anyways, comparing with other languages is a little bit offtopic what are out strenghts, and what problems can we solve? i make a game with D, what are you guys doing with D?should compare D is with (actually 3) Go/Rust/Zig it compiles to IL and requires a massive runtime with the graveyard of old and irrelevant techSo much disinformation. https://docs.microsoft.com/en-us/windows/uwp/dotnet-native/ https://docs.microsoft.com/en-us/dotnet/framework/tools/ngen-exe-native-image-generator https://github.com/dotnet/designs/blob/main/accepted/2020/form-factors.md#native-aot-form-factors https://docs.microsoft.com/en-us/xamarin/mac/internals/aot https://docs.unity3d.com/Manual/IL2CPP.html Running on production embedded hardware, https://www.wildernesslabs.co Apparently the majority of the games running in that Nintendo toy, that has broken all sale records, happen to use Unity in about 30% of their titles. https://www.kelltontech.com/kellton-tech-blog/reasons-develop-nintendo-switch-games-in-unity-game-engine Another graveyard irrelevant technology that besides Nintendo, is the tier 1 for Sony, Google and Microsoft gaming systems and AR/VR platforms, alongside Unreal. Looks pretty much alive to me. D also compiles to LDC bitcode and GCC gimple, and has a runtime. Should we also consider it not a systems language then? Don't let the hatred and lack of knowledge for other stacks cloud your judgement. It steers people away from D when false statements are being done about the ecosystems they know quite well, turning on their defences and thus stop listening on what D is actually supposed to be better on.
Oct 09 2021
On Thursday, 7 October 2021 at 22:07:13 UTC, Guillaume Piolat wrote:D having one front-end means that in practice you have less unknowns.I think that could well be one of our strongest advantages against C++, since UB stuff can also have a reference point for implementation, meaning vendors don't _have_ to guess something when implementing a corner case.Yes really, it is very difficult to keep up with the C++ changes even if you were a full-time C++ programmer. And you need to since people start to use the new stuff when available. It is very likely that when the next standard comes out, you would have barely assimilated the one from 10 years ago. C++ needs a cast of "explainers" like Scott Meyers.The last 10 years have really been a roller-coaster for C++ practitioners, but I think it's necessary for the language to evolve at that breakneck pace to at-least be relevant. Imagine if Rust and D and Nim and whatever fail to replace C++? If the C++ recommended in use is still the same as C++03? That would've been a nightmare. C++20 and its successors won't be very good languages in their own right, but for the jobs that they're expected to perform(be 100% compatible with existing code), they'll be perfect, unfortunately.
Oct 08 2021
On Friday, 8 October 2021 at 10:58:00 UTC, Tejas wrote:On Thursday, 7 October 2021 at 22:07:13 UTC, Guillaume Piolat wrote:This is why I'm still so ambivalent on what I should do with C++ 😭[...]I think that could well be one of our strongest advantages against C++, since UB stuff can also have a reference point for implementation, meaning vendors don't _have_ to guess something when implementing a corner case. [...]
Oct 08 2021
On Thursday, 7 October 2021 at 22:07:13 UTC, Guillaume Piolat wrote:On Thursday, 7 October 2021 at 20:12:49 UTC, Dukc wrote:I was thinking about the frontend. Some C++ frontends are so widely used that I'd think they have less bugs. OTOH C++ frontends are more complex to get right and they are not written in D (except DMC), so I would not except a C++ frontend of similar maturity to be as reliable. But something lice g++ is so incredibly common that it sounds like a bigger factor than the relative simplicity of D.Wow, are modern C++ compilers crashy *when compared to D*? I definitely agree that D compilers nowadays are more than stable enough for production, but do they really rival the most common C++ ones?LDC rivals clang of course. On what metric do you think it wouldn't?Yes really, it is very difficult to keep up with the C++ changes even if you were a full-time C++ programmer. And you need to since people start to use the new stuff when available. It is very likely that when the next standard comes out, you would have barely assimilated the one from 10 years ago. C++ needs a cast of "explainers" like Scott Meyers.Ouch. They would do well to be more conservative and leave accumulating features for extensions and younger languages. They cannot match newer languages in elegance whatever they do, so it'd make more sense to make life easy for existing codebases instead. But I'm probably missing something here. I don't think the C++ standard committee is stupid after all.
Oct 10 2021
On Sunday, 10 October 2021 at 17:07:04 UTC, Dukc wrote:On Thursday, 7 October 2021 at 22:07:13 UTC, Guillaume Piolat wrote:C++ has hypernormalized a very language-lawyery way of programming. The committee isn't stupid but the road to hell is paved with good intentions, as they say. Any decision than make can be inverted and justified just as easily, from what I have read.[...]I was thinking about the frontend. Some C++ frontends are so widely used that I'd think they have less bugs. OTOH C++ frontends are more complex to get right and they are not written in D (except DMC), so I would not except a C++ frontend of similar maturity to be as reliable. But something lice g++ is so incredibly common that it sounds like a bigger factor than the relative simplicity of D.[...]Ouch. They would do well to be more conservative and leave accumulating features for extensions and younger languages. They cannot match newer languages in elegance whatever they do, so it'd make more sense to make life easy for existing codebases instead. But I'm probably missing something here. I don't think the C++ standard committee is stupid after all.
Oct 10 2021
On Wed, Oct 06, 2021 at 11:26:14PM +0000, Tejas via Digitalmars-d wrote: [...]Why do you continue to walk the path less travelled when others enjoy the advantages of mainstream languages like better tooling and greater stability, ie, fewer/no breaking changes with each release(and disadvantages like various janky workarounds for backwards compatibility, deigns/ideological constraints, etc)?Speaking for myself only here: (1) I have very little concern about walking less travelled paths; IME popularity does not correlate with quality. Javascript is one of the most popular languages out there, but from a design perspective it's trash. No real OO, you fake it with prototypes (or whatever it is they call 'em), fragile error handling, tons of WATs (== vs ===, weird implicit conversions between strings, integers, floats, etc.), debugging is a royal pain.[*] The only reason JS is still afloat is because its disproportionate popularity draws in enough manpower to barrel through problems. On the contrary, better-designed languages tend to be the less popular ones. (2) I have all the tooling I need for efficient work with D (vim + compiler + Unix shell == yeahhh). Though I understand I'm in the far minority on this point. :-D (3) Breaking changes with each release happens not just with D. I have some very old C++ projects dating from the 90's, and I can tell you that trying to get them to compile with a modern compiler is an exercise in pain. The only reason people don't complain about this very much is because D releases much more frequently than C++. Janky workarounds for C++ code are pretty much so widely-accepted that you don't even think twice, you just insert const casts everywhere, insert compiler switches to suppress errors/warnings, use macro hacks to patch over stuff just for Mt Cesuaga (Making That Compile Error Shut Up And Go Away), etc.. By comparison, D workarounds are a walk in the park. (4) Ideological constraints: I find D the most liberating in this respect, actually. Javascript forces you to fake things like OO with its weird backwards prototype-based ideology, Java constrains you to shoehorn the most unlikely things into OO-sanctioned constructs, and because full-on template-style generics are considered "too dangerous" for the unwashed masses to consume (don't even get me start on Go, which doesn't even have generics), leading to boilerplate galore; functional languages force you to rephrase the simplest of imperative constructs in a functional guise, etc.. With D, I can choose the best paradigm for the problem at hand without needing to pay lip service to some ideological ideal that doesn't actually map well to the problem domain. OO when I need OO, functional when I need functional, bare pointers and asm for when I need to go under the hood to solder wires together, so to speak. Of course, that's not to say D doesn't have its own set of problems. But in comparison with the other languages I've experienced so far, D has the least of the problems in exchange for the most of the benefits. // ([*] Once, I had the misfortune of having a complex, ill-maintained JS project dumped on my lap at work. Most bugs in that code manifested themselves in a blank page with no other traces of the problem. The browser's debug console was useless because somebody "helpfully" installed an exception catcher that deliberately swallows errors. Worse yet, one of our support targets at the time was IE6, which did NOT have a debug console at all. It was a lot of "fun" debugging problems specific to IE. JS is indeed the epitome of a popular language with better tooling and greater stability.</sarcasm>) T -- Любишь кататься - люби и саночки возить.
Oct 07 2021
On Thursday, 7 October 2021 at 21:59:26 UTC, H. S. Teoh wrote:Speaking for myself only here: (1) I have very little concern about walking less travelled paths; IME popularity does not correlate with quality. Javascript is one of the most popular languages out there, but from a design perspective it's trash. No real OO, you fake it with prototypes (or whatever it is they call 'em), fragile error handling, tons of WATs (== vs ===, weird implicit conversions between strings, integers, floats, etc.), debugging is a royal pain.[*] The only reason JS is still afloat is because its disproportionate popularity draws in enough manpower to barrel through problems. On the contrary, better-designed languages tend to be the less popular ones.Yeah JS is a royal pain, but now TS has become a true alternative. The shops that are stuck with JS for some reason are stuck with it; but I think we should now compare with TS if we will ever talk about web stuff, since practically all new projects start with TS now.(2) I have all the tooling I need for efficient work with D (vim + compiler + Unix shell == yeahhh). Though I understand I'm in the far minority on this point. :-DSame here :D(3) Breaking changes with each release happens not just with D. I have some very old C++ projects dating from the 90's, and I can tell you that trying to get them to compile with a modern compiler is an exercise in pain. The only reason people don't complain about this very much is because D releases much more frequently than C++. Janky workarounds for C++ code are pretty much so widely-accepted that you don't even think twice, you just insert const casts everywhere, insert compiler switches to suppress errors/warnings, use macro hacks to patch over stuff just for Mt Cesuaga (Making That Compile Error Shut Up And Go Away), etc.. By comparison, D workarounds are a walk in the park.I think C++ has more robust backwards compatibility. The latest (mainstream) C++ compiler(s) can easily compile code written in 2010. But I doubt the latest D compilers can do so. Sure, it might get painful if we go 20 years behind, but C++ is still better in that department, in D you can't even imagine having that degree of support(yet, hopefully).(4) Ideological constraints: I find D the most liberating in this respect, actually. Javascript forces you to fake things like OO with its weird backwards prototype-based ideology, Java constrains you to shoehorn the most unlikely things into endure a watered-down generics system because full-on template-style generics are considered "too dangerous" for the unwashed masses to consume (don't even get me start on Go, which doesn't even have generics), leading to boilerplate galore; functional languages force you to rephrase the simplest of imperative constructs in a functional guise, etc.. With D, I can choose the best paradigm for the problem at hand without needing to pay lip service to some ideological ideal that doesn't actually map well to the problem domain. OO when I need OO, functional when I need functional, bare pointers and asm for when I need to go under the hood to solder wires together, so to speak.Yeah, but you don't think that could lead to inconsistencies? Like the other languages are subscribed to a specific paradigm so certain constructs might appear unnatural, but atleast they might be _consistently_ unnatural? I hope our flexibility doesn't result in `perl` style only-I-can-read-my-code, but actually goes closer to `python`'s there-should-be-only-one-way-to-do-it.Of course, that's not to say D doesn't have its own set of problems. But in comparison with the other languages I've experienced so far, D has the least of the problems in exchange for the most of the benefits. // ([*] Once, I had the misfortune of having a complex, ill-maintained JS project dumped on my lap at work. Most bugs in that code manifested themselves in a blank page with no other traces of the problem. The browser's debug console was useless because somebody "helpfully" installed an exception catcher that deliberately swallows errors. Worse yet, one of our support targets at the time was IE6, which did NOT have a debug console at all. It was a lot of "fun" debugging problems specific to IE. JS is indeed the epitome of a popular language with better tooling and greater stability.\</sarcasm>)Eeeek D:
Oct 08 2021
On Monday, 4 October 2021 at 22:15:33 UTC, Walter Bright wrote:Interestingly, left off is one thing that D does very well at: plasticity. What do I mean by that? I've been developing code for a loooong time. I've noticed a couple long term trends with C and C++ code. One is brittleness. This manifests itself in the strange characteristic that no matter how many years I work on a piece of code, the very first organization of it and the structure of it never fundamentally changes. Oh, I endlessly tweak it and optimize it and enhance it, but it's still the original design under the hood. I.e. it is brittle. With D code, however, I've found it to be far easier to change the design. Optimization becomes not so much sweating the details, but lowered barriers to trying out different designs to see what works better. I did this extensively on the Warp preprocessor project. I discovered a key component of this is D's use of . instead of ->. One can easily test drive with classes, structs, pointers, and values, interchanging them as one would try on a shirt. It's such a frackin' nuisance to do that in C and C++, one just doesn't bother. This is plasticity, the opposite of brittleness. What are your experiences with this?I've experienced this too. In D, with a little ingenuity, it is possible to make almost any surface-level syntax "desugar" to almost anything you want. Which means that when you want to change how some part of your program is implemented, you can almost always keep the original syntactic "interface" stable while doing so. There are a lot of little language features that add up to make this possible. Implicit pointer dereferencing (as you mention), UFCS, optional parentheses, IFTI, operator overloading...probably some more that I'm forgetting. I think this "plasticity" is probably closely related to "expressiveness", because the language features that contribute to one tend to also contribute to the other. Depending on how you interpret "expressiveness", they might even be the same thing (something like, "number of possible 'implementations' for a given piece of syntax").
Oct 04 2021
On Mon, Oct 04, 2021 at 11:39:05PM +0000, Paul Backus via Digitalmars-d wrote:On Monday, 4 October 2021 at 22:15:33 UTC, Walter Bright wrote:[...]Interestingly, left off is one thing that D does very well at: plasticity. What do I mean by that?I've totally experienced this. Some of my personal projects started out as one-off, throwaway scripts, ugly, full of hacks, crazy one-liners, etc.. But as time went on, it got refactored, cleaned up, sprouted modules, packages, and gradually transformed itself into a set of well-encapsulated components interacting with each other through nice APIs, as though it were something designed that way from the beginning. The use of '.' for what C/C++ use '.' and '->' for is one of the factors in making this possible. I'd even go further and say that the coincidence of '.' (as in member access) with '.' (as in FQN separator) allows certain refactorings that involve substituting a package/module with a nested variable. (Actual example: to make I/O code more unittestable, sometimes I insert an `alias stdio = std.stdio` template parameter into my function; that way, the unittest can substitute std.stdio with a mock-up struct that emulates std.stdio without performing actual I/O. Had the FQN separator been different from the member access operator, this would've been impossible.) Optional parentheses is another - it's easy to turn a public mutable field into a properly-encapsulated access method without needing to rewrite a whole bunch of code. Conversely, a method used like a field can be substituted with an actual field, should that become necessary for whatever reason. Type inference and Voldemort types (much as people criticize it) makes it possible to change the return value of some function without suddenly making a whole ton of code uncompilable. Indeed, I've come to adopt the practice of using `auto` whenever the code I'm writing technically doesn't need to care what the concrete type is (which is quite a lot of the time -- it applies even if you access some field in the type, because all that requires is that it be any type for which .xyz returns a value; it can be a public field, an access method, a UFCS function on an int, whatever). UFCS + IFTI also lets you abstract away the implementation details of entire chains of processing, so you can change any number of intermediate types in between without needing to touch the chain itself at all. [...]I discovered a key component of this is D's use of . instead of ->. One can easily test drive with classes, structs, pointers, and values, interchanging them as one would try on a shirt. It's such a frackin' nuisance to do that in C and C++, one just doesn't bother. This is plasticity, the opposite of brittleness. What are your experiences with this?I've experienced this too. In D, with a little ingenuity, it is possible to make almost any surface-level syntax "desugar" to almost anything you want. Which means that when you want to change how some part of your program is implemented, you can almost always keep the original syntactic "interface" stable while doing so.I think this "plasticity" is probably closely related to "expressiveness", because the language features that contribute to one tend to also contribute to the other.[...] IMO, the plasticity comes from what I call "symmetry", by which I mean the mathematical (not aesthetic) sense of symmetry: some object X remains unchanged under some set of operations Y. More specifically, in D there's a lot of "syntactic symmetry": some given piece of syntax such as a line of code (the "object") remains unchanged under many forms of refactorings (the "operations"). Such swapping out the types involved in that line of code, changing something from class to struct, etc.. The greater the syntactic symmetry of a piece of code under the set of refactorings, the easier it is to refactor the program while making only minimal changes to the surface level code. For example, UFCS chains. By constraining the API of each component of the chain to the range API, the chain becomes symmetric under many refactoring operations like inserting/removing a component, substituting one component for another, changing the concrete element types of a component, reordering components (to some extent -- if the relevant types are compatible), etc.. This symmetry makes it easy to change the code: the syntax of the chain remains unchanged under the operation of changing a return type, for example, so you only need to change the return type, you don't have to change the syntax of the chain. The range API serves as the invariant amid these refactoring operations, and this gives range-based code a high degree of symmetry under said refactorings. DbI is a another powerful example: by using static if to discover the properties of a template argument instead of making assumptions about the existence of, e.g., some property .xyz, you make that template symmetric under the operation of swapping that argument for another type that may not have a .xyz property. The template adapts itself to the new argument, instead of no longer compiling because the .xyz that was present in the old type doesn't exist in the new. The body of the template remains unchanged in the face of the change in behaviour of the incoming type. Symmetry. On the converse side, the lack of symmetry in certain aspects of the language makes certain refactorings more difficult. One example is the struct/class by-value/by-ref dichotomy. While certain refactorings let you get away with simply writing `struct` in the place of `class`, if there's code that depends on the by-ref nature of the class, then more effort will be required to maintain the correctness of the code, e.g., inserting `ref` into function parameters in order to emulate the by-ref behaviour of the class. Another example is D's integer promotion rules. If for whatever reason you wish to change `int` to `short`, for example, you'll quickly run into trouble with arithmetic expressions that now require a cast in order to be assignable back to a short. I'm sure you can find many other examples of asymmetry in D, but IMO D does have a high degree of symmetry in many of the right places, and that makes D code highly refactorable and plastic. In other languages, there tends to be a lot of asymmetry under many refactoring operations, which makes it difficult to perform certain kinds of refactorings. This effectively de-incentivises said refactorings, making the language less plastic and programs less refactorable. T -- Spaghetti code may be tangly, but lasagna code is just cheesy.
Oct 04 2021
On 10/4/21 3:15 PM, Walter Bright wrote:This is plasticity, the opposite of brittleness. What are your experiences with this?That is exactly the case! (I wrote my response to H. S. Teoh before reading your post.) "Plasticity" seems to be a common theme about D. Ali
Oct 04 2021
On 10/4/2021 5:15 PM, Ali Çehreli wrote:That is exactly the case! (I wrote my response to H. S. Teoh before reading your post.)Hmm, I should have read your post first!
Oct 04 2021
On Monday, 4 October 2021 at 22:15:33 UTC, Walter Bright wrote:This is plasticity, the opposite of brittleness.To me, that's just another case of abstraction. D's '.' abstracts the details of '.' and '->'. That naturally leads to plasticity - ability to swap concrete things without affecting the abstract interface.
Oct 05 2021
On Tue, Oct 05, 2021 at 08:22:48AM +0000, Max Samukha via Digitalmars-d wrote:On Monday, 4 October 2021 at 22:15:33 UTC, Walter Bright wrote:It's more than just '.' vs '.' and '->', though. That's just one of the smaller details that lead to plasticity. Other factors include type inference: by using type inference where the code doesn't really depend on a specific concrete type, you allow that type to be swapped for another one later on without needing to change that part of the code. This is particularly powerful in UFCS chains: if you had to implement the UFCS chain in C, for example, you'd have to rewrite a whole bunch of types, variable declarations, etc., every time you need to do something like insert a new component into the chain, or reorder the chain. That makes refactoring the equivalent code in C an onerous task, which naturally incentivizes people *not* to do such a refactoring in C. In D, thanks to type inference, it takes just a few seconds to perform this refactoring. That opens the door to refactoring your program in ways you normally don't do in C, and much more frequently too. Another factor is built-in unittests: if your code has an adequate set of unittests, you're far more likely to do larger-scale refactorings, because the unittests give you confidence that any glaring mistakes would be instantly caught. In C, unless you have a solid unittesting framework in place (how many C projects have you seen that has this? IME, it's in the far minority), you'd have no confidence at all that your refactoring wouldn't introduce new bugs, esp. subtle bugs that will come back to bite you in the worst possible ways. This factor doesn't stand by itself; D code tends to be more testable thanks to incentives to write things like UFCS chains instead of deeply-nested loops. As a result, if properly used, unittests tend to be more thorough than an external testsuite as is common in C projects that have a testsuite (unfortunately, most C projects don't even have one). Which in turn leads to higher confidence level that you won't introduce bugs during refactoring. Template functions with DbI also adds to D's plasticity: by using static if's to discover properties of incoming types and adapting to them accordingly, a function can retain the same external API while increasing in functionality. As I described in my other post with the example of a serialization function, DbI allows the caller to remain unchanged in the face of changing types and changing requirements like excluding certain fields from serialization, or different serialization strategies for different types. In the equivalent C code, you'd have to write a different serialization function per type, or use error-prone APIs that pass in void* and type sizes (not to mention nested information for nested types -- the complexity just explodes). And every time you switch the type being serialized, you'd have to change every callsite that passes that type. To handle things like non-serialized fields, you'd have to hard-code stuff into the serialization functions or pass unwieldy structures like lists or hashtables of stuff to exclude, stuff that need special treatment, etc.. It's a lot of tedious (and error-prone!) busywork just to do a refactoring that in D constitutes just a few lines of code change. So naturally, in C you'd rather avoid such refactorings, preferring instead to keep the existing design so as to avoid breaking things unintentionally or spending too much time refactoring stuff that already works. In D, you're freed from a lot of such concerns, so are more likely to perform deep refactorings that change the original design in more drastic ways. T -- Question authority. Don't ask why, just do it.This is plasticity, the opposite of brittleness.To me, that's just another case of abstraction. D's '.' abstracts the details of '.' and '->'. That naturally leads to plasticity - ability to swap concrete things without affecting the abstract interface.
Oct 05 2021
On Tuesday, 5 October 2021 at 17:53:46 UTC, H. S. Teoh wrote:This is particularly powerful in UFCS chains: if you had to implement the UFCS chain in C, for example, you'd have to rewrite a whole bunch of types, variable declarations, etc., every time you need to do something like insert a new component into the chain, or reorder the chain. That makes refactoring the equivalent code in C an onerous task,This is all great, but C is too weak a competitor for it to be persuasive to someone who needs persuading. Here's a remark on brittleness in Rust:I’ve seen this many times in Rust: I write a large chunk of code being a little careless about lifetimes, just to then have to change the types of my variables and functions everywhere in my program to avoid having to clone() things everywhere to make it work.from https://renato.athaydes.com/posts/how-to-write-slow-rust-code.html
Oct 05 2021
On Tuesday, 5 October 2021 at 20:00:42 UTC, jfondren wrote:On Tuesday, 5 October 2021 at 17:53:46 UTC, H. S. Teoh wrote:Interesting link about Rust. I think D could/should speak to those wanting to be more productive 🍀[...]This is all great, but C is too weak a competitor for it to be persuasive to someone who needs persuading. Here's a remark on brittleness in Rust:[...]from https://renato.athaydes.com/posts/how-to-write-slow-rust-code.html
Oct 05 2021
On Tuesday, 5 October 2021 at 20:00:42 UTC, jfondren wrote:On Tuesday, 5 October 2021 at 17:53:46 UTC, H. S. Teoh wrote:C has the whole market of UNIX clones, Khronos standards, and embedded for itself, where C++ after 30 years trying hardly managed to make dent.This is particularly powerful in UFCS chains: if you had to implement the UFCS chain in C, for example, you'd have to rewrite a whole bunch of types, variable declarations, etc., every time you need to do something like insert a new component into the chain, or reorder the chain. That makes refactoring the equivalent code in C an onerous task,This is all great, but C is too weak a competitor for it to be persuasive to someone who needs persuading.
Oct 05 2021
On 10/5/2021 10:53 AM, H. S. Teoh wrote:Another factor is built-in unittests: if your code has an adequate set of unittests, you're far more likely to do larger-scale refactorings, because the unittests give you confidence that any glaring mistakes would be instantly caught.This is why D's test suite is so crucial. We could never improve D without it. The *lack* of a test suite for Optlink is what is killing it. It being all written in assembler isn't the issue.
Oct 05 2021
On Tuesday, 5 October 2021 at 17:53:46 UTC, H. S. Teoh wrote:So naturally, in C you'd rather avoid such refactorings, preferring instead to keep the existing design so as to avoid breaking things unintentionally or spending too much time refactoring stuff that already works. In D, you're freed from a lot of such concerns, so are more likely to perform deep refactorings that change the original design in more drastic ways. TYeah, D is better than C in that respect.
Oct 07 2021
On Monday, 4 October 2021 at 22:15:33 UTC, Walter Bright wrote:What are your experiences with this?Pretty much. At a superficial level D is a language that says "yes" to most things. Can I have that feature? Yes. Can I move this piece of code there? Yes. Can I reuse that C/C++ code? Yes, you can. So that's the "liberal" part, the low mental-friction that makes you do things. Bounds check and variable initializaton participate in that, since you win precious time. Because the first task of any software is to exist and be useful, at a reasonable cost. And that's great because that's where most program need to stop, as garbage internal tools or experiments. So D has attracted a lot of lonewolves types - for better and worse - and it shapes the culture. The other parts are the restrictions, you can add qualifiers to increase quality, and the language will gently remind you that safety is important. D strives to strike a balance for large-scale wasteland programming. It is the mature C++ that depart from the "MAX POWER" ethos to give instead actionnable power that you don't come to regret later. Some features you really appreciated in a hellish maintenance context. So D strikes me as a thing of balance, its values are somewhat "bring your own values" and of course the marketing message isn't hitting as hard and fast as imbalanced languages.
Oct 05 2021
On 10/4/21 6:15 PM, Walter Bright wrote:This is plasticity, the opposite of brittleness. What are your experiences with this?For the most part, it's great! There is one place where I have struggled though, and D might be able to do better. And that is with optional parentheses and taking the address. When a property can be either an accessor or a field, then `obj.prop` can work the same. However, `&obj.prop` is not the same. I have solved it by using this stupid function: ```d auto ref eval(T)(auto ref T t) { return t; } // instead of &obj.prop auto ptr = &eval(obj.prop); ``` I just came across this workaround in my code and since I wrote it a long time ago it puzzled me "what is this `eval` function?". Took me a minute to remember why I did that. While it's nice D has a mechanism to work around this difference, I find having to use such shims a bit awkward. And it's a direct consequence of hiding the implementation of a field/property behind the same syntax. You can find other cases where D can be awkward (such as `typeof(obj.prop)` or checking types regardless of mutability). What is the "better" answer though? I don't know. -Steve
Oct 06 2021
On Wednesday, 6 October 2021 at 15:59:46 UTC, Steven Schveighoffer wrote:On 10/4/21 6:15 PM, Walter Bright wrote:This is something I agree with. I often come across small snippets of code that I've made and I sometimes can't remember why I did something like it, until I try it and then it's like "oh yeah it was to work around this thing"This is plasticity, the opposite of brittleness. What are your experiences with this?For the most part, it's great! There is one place where I have struggled though, and D might be able to do better. And that is with optional parentheses and taking the address. When a property can be either an accessor or a field, then `obj.prop` can work the same. However, `&obj.prop` is not the same. I have solved it by using this stupid function: ```d auto ref eval(T)(auto ref T t) { return t; } // instead of &obj.prop auto ptr = &eval(obj.prop); ``` I just came across this workaround in my code and since I wrote it a long time ago it puzzled me "what is this `eval` function?". Took me a minute to remember why I did that. While it's nice D has a mechanism to work around this difference, I find having to use such shims a bit awkward. And it's a direct consequence of hiding the implementation of a field/property behind the same syntax. You can find other cases where D can be awkward (such as `typeof(obj.prop)` or checking types regardless of mutability). What is the "better" answer though? I don't know. -Steve
Oct 06 2021
We've known about this ambiguity issue for a long time. Unfortunately, we were never able to figure out a solution that would accommodate existing, extensive practice. I.e. it's a design mistake I made early on that we're stuck with.
Oct 06 2021
On Wednesday, 6 October 2021 at 22:23:17 UTC, Walter Bright wrote:We've known about this ambiguity issue for a long time. Unfortunately, we were never able to figure out a solution that would accommodate existing, extensive practice. I.e. it's a design mistake I made early on that we're stuck with.Well D makes up for it with its many other great features :) Tbh. it's a minor thing.
Oct 07 2021
On Wed, Oct 06, 2021 at 11:59:46AM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]There is one place where I have struggled though, and D might be able to do better. And that is with optional parentheses and taking the address. When a property can be either an accessor or a field, then `obj.prop` can work the same. However, `&obj.prop` is not the same. I have solved it by using this stupid function: ```d auto ref eval(T)(auto ref T t) { return t; } // instead of &obj.prop auto ptr = &eval(obj.prop); ```IMO, taking the address of something is a low-level operation that doesn't really belong in higher-level logic. Unsurprisingly, therefore, it doesn't lend itself well to the malleability that generally applies in D code. The fact of taking the address of something imposes the implicit assumption that that object has an address to be taken in the first place. Meaning that once you use such an operation, the target object is no longer Liskov-substitutable with anything else that may not have an address (e.g. an accessor function). So this imposes limitations on what kinds of refactoring the code will be amenable to. Generally, I like to think of unary & as something that should only be used in lower-level modules in the code, where it's acceptable to have to rewrite some more code in order to make & work nicely. For higher-level modules I prefer to stay away from such operations, because they make the code less refactorable. [...]While it's nice D has a mechanism to work around this difference, I find having to use such shims a bit awkward. And it's a direct consequence of hiding the implementation of a field/property behind the same syntax. You can find other cases where D can be awkward (such as `typeof(obj.prop)` or checking types regardless of mutability). What is the "better" answer though? I don't know.[...] Not necessarily a better answer: static if to discover whether something is a field or an accessor, and extract the address appropriately, possibly encapsulated in a utility function? Not much different from your .eval hack, though. The C++ answer is to allow overloading of unary &. However, that opens up a whole 'nother can o' worms that I would not recommend. T -- This is not a sentence.
Oct 07 2021
On 10/7/21 1:35 PM, H. S. Teoh wrote:On Wed, Oct 06, 2021 at 11:59:46AM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]To give more context, it is solely for this little function: ```d auto firstElem(R)(R r) if (hasLvalueElements!R) { if(r.empty) return null; return &(eval(r.front)); } ``` Why do I need this function? Because Phobos doesn't give me nice access to things from `find`. Instead, it gives me a range. Which is useful for some cases, but for others, I just want to get reference access of the element I was looking for. So compare the two possibilities: ```d auto result = someRange.find(elem); if(!result.empty) { if(result.front.x > 5) result.front.x -= 5; } // vs. if(auto v = someRange.find(elem).firstElem) { if(v.x > 5) v.x -= 5; } ``` For some things, pointers are the best interface. Sure, I could wrap this up in a type, but it still would need to store a pointer internally (or the range itself), plus a pointer is already doing exactly what I need it to do. The main issue is that `obj.method` means different things depending on context. As kind of another similar story, A long time ago, an eponymous template allowed some access to things inside the template, and did not always map directly to the eponymous member *in some situations*. While this allowed greater flexibility, it produced odd behavior. Eventually, all access of the internals of an eponymous template were removed, and it always *always* just means the eponymous member. This removed some expressiveness, but the result is much much cleaner. I would like to see something similar for property methods.There is one place where I have struggled though, and D might be able to do better. And that is with optional parentheses and taking the address. When a property can be either an accessor or a field, then `obj.prop` can work the same. However, `&obj.prop` is not the same. I have solved it by using this stupid function: ```d auto ref eval(T)(auto ref T t) { return t; } // instead of &obj.prop auto ptr = &eval(obj.prop); ```IMO, taking the address of something is a low-level operation that doesn't really belong in higher-level logic. Unsurprisingly, therefore, it doesn't lend itself well to the malleability that generally applies in D code. The fact of taking the address of something imposes the implicit assumption that that object has an address to be taken in the first place. Meaning that once you use such an operation, the target object is no longer Liskov-substitutable with anything else that may not have an address (e.g. an accessor function). So this imposes limitations on what kinds of refactoring the code will be amenable to.[...]This would be horrid. Basically, your code starts looking like: ```d static if(isAccessor!(obj.foo)) // have fun writing this, there's lots of traps. return &obj.foo(); else return &obj.foo; ``` The eval hack is much much cleaner. It means "this is an expression, not a symbol". Maybe the answer is to do this with some syntax feature, so I can avoid calling silly hack functions.While it's nice D has a mechanism to work around this difference, I find having to use such shims a bit awkward. And it's a direct consequence of hiding the implementation of a field/property behind the same syntax. You can find other cases where D can be awkward (such as `typeof(obj.prop)` or checking types regardless of mutability). What is the "better" answer though? I don't know.[...] Not necessarily a better answer: static if to discover whether something is a field or an accessor, and extract the address appropriately, possibly encapsulated in a utility function? Not much different from your .eval hack, though.The C++ answer is to allow overloading of unary &. However, that opens up a whole 'nother can o' worms that I would not recommend.Nope, I would never want that. I want a pointer when I ask for a pointer. -Steve
Oct 08 2021
On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:In ["Rust and Other Interesting Things"][1], Bryan Cantrill talks about the importance of a programming language's *values*....Approachability Integrity Robustness Availability Maintainability Safety Compatibility Measurability Security Composability Operability Simplicity Debuggability Performance Stability Expressiveness Portability Thoroughness Extensibility Resiliency Transparency Interoperability Rigor Velocity I thought it might be fun to ask the D community: **which of the above values do you think are the most important to D? Choose no more than 5, and reply with your answer!**From my experience: Use case: replacing 2 executables with one written in D in a system consisting of multiple executables all written in C++ using various libraries and a proprietary bus system originally designed and build in 2004. **Approachability + Expressiveness**: almost without any friction to get started in D coming from more than 20 years primarily C++ the code written seems to be better at expressing intend than any of the other languages I've used. More succinct code, less comments needed for 'explaining'. **Composability + Interoperability**: The language and its facilities made it very easy to plug and plump together the solution based on various D C++ and C components. Exchanging one implementation with another approach went very smooth in the D based code. **Stability + Safety**: Unit test in D are godsend, it saved me from various logic errors/misses in edge cases. The compiler (language) saved me several times by erroring out helping and telling me what is unsafe. In general my experience is once a D compiler produces a binary, it almost never crashes due to stupid mistakes which happens in C++ quite often like out of bound access, not proper initialized objects null pointer derefs etc. Also I had the impression the functional completeness was much quicker reached, because there was almost no time needed and so no distraction from actual problem solving to get the darn thing to run. Another observation I made is: the final solution barely uses classes. D module system as unit of encapsulation seems perfectly fit for purpose.
Oct 08 2021
On 10/8/21 2:53 AM, Arjan wrote:From my experience: Use case: replacing 2 executables with one written in D in a system consisting of multiple executables all written in C++ using various libraries and a proprietary bus system originally designed and build in 2004.Are you sure it worked? Because Bjarne thinks "it doesn't work". ;) https://youtu.be/ae6nFZn3auQ?t=2228 Ali P.S. More interesting bits from the video: After praising C++'s Core Guidelines (which contains 400+ rules by my last count) for years (and introducing it with a bang along with Herb Sutter at a C++ conference, reference of which I can't find anymore), he contradicts himself by saying "humans are not actually very good at following rules": https://youtu.be/ae6nFZn3auQ?t=2039 Of course, ultimate blame for C++ bugs goes to "static analysis community": https://youtu.be/ae6nFZn3auQ?t=2345 So, perhaps I misunderstood the guidelines: They were not for humans to begin with? Nah! They were and are for humans. I followed similar C++ rules personally for about 20 years. Despite Bjarne's understanding the value of fat pointers (D's slices): https://youtu.be/ae6nFZn3auQ?t=2145 ... he does not think "the solution is necessarily another language": https://youtu.be/ae6nFZn3auQ?t=1758 I watched the video only between minutes 29 and 42, so there may be more gems in there.
Oct 08 2021
On Friday, 8 October 2021 at 16:37:51 UTC, Ali Çehreli wrote:On 10/8/21 2:53 AM, Arjan wrote:Thanks for the links. Interesting but I do not concur with those statements of Bjarne. Multiple times it has been proven already to be FUD. The chances of success has not so much to do with the languages from to, but much more on the approach, the availability of verification devices etc. Also here in this forum multiple times has been reported great success with transitioning to D from other languages. What make D interesting imo is that it is very broad in fit for purpose. This is were it hugely is distinct from any other language i'm aware of.From my experience: Use case: replacing 2 executables with one written in D in asystemconsisting of multiple executables all written in C++ usingvariouslibraries and a proprietary bus system originally designedand build in2004.Are you sure it worked? Because Bjarne thinks "it doesn't work". ;) https://youtu.be/ae6nFZn3auQ?t=2228
Oct 11 2021
On 10/11/21 5:21 AM, Arjan wrote:Are you sure it worked? Because Bjarne thinks "it doesn't work". ;) https://youtu.be/ae6nFZn3auQ?t=2228Thanks for the links. Interesting but I do not concur with those statements of Bjarne.Neither do I. My sarcastic winky was too subtle? :) There is something fishy when a professor discourages new language design and especially one who acts as if D and other languages don't exist. Ali
Oct 11 2021
On Tuesday, 12 October 2021 at 03:16:11 UTC, Ali Çehreli wrote:There is something fishy when a professor discourages new language design and especially one who acts as if D and other languages don't exist.Did we view the same clip? He seemed to argue that reimplementing 12 million lines of C code into a new language does not solve the issues effectively, but gradually transitioning into a language with better static checks does solve issues effectively. And that is probably true for code that is a natural fit for C. Of course, these days, most problems are not a natural fit for C or C++…
Nov 03 2021
On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:I thought it might be fun to ask the D community: **which of the above values do you think are the most important to D? Choose no more than 5, and reply with your answer!**Not the focus of the subsequent thread, but here are my answers should someone collate responses: Irybpvgl Cresbeznapr Rkcerffvirarff Vagrebcrenovyvgl Fnsrgl
Oct 08 2021
On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:I thought it might be fun to ask the D community: **which of the above values do you think are the most important to D?A little while back I evaluated Go, Rust, D as a replacement for the split python/C I'd been using for my day to day working language. I wanted a compiled language, so that simple code was also fast. I was still irritated with C++ template noise so, maybe unfairly, I ruled that out. In order not to sway my reasons, I haven't looked at the list of values, but here's five aspects I appreciated. 1. Humility - The language did not try to evangelize a one-right-way(tm) to do everything. It laid out a big tool box and trusted me* as the programmer to pick the best approach for the job. 2. Compatibility - I still have a lot of C code lying around. Calling into C libraries is an absolute minimum requirement. 3. Completeness - With operator overloading, associative arrays, classes, lambda functions and yes, garbage collection, I'm given a wide range of tools for turning ideas into code. 4. Competence - After reading Andrei's book and browsing this forum I came to the opinion that seriously clever people were behind D. 5. Fun - The community seemed to be having fun with D. That sentiment started with the name. -- *probably more then it should, but hey, flattery is nice.
Oct 08 2021
On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:[...]D is all about choice. Many people feel frustrated with D: safe, live, nogc, betterC, etc - what/when to use? They ultimately feel lost. But it's not a language thing. D lets the programmer make the choices and helps him stay true to what he has chosen. D is like C - it trusts the programmer, but it also has the necessary mechanisms to ensure that the programmer does not stray from the path chosen. Want to avoid the GC? Put nogc at the top of your file. Do you want your code to be safe? safe - is the way to go. Such mechanisms ensure you don't get lazy and start using the features you set to avoid. Unlike Rust, D does not enforce anything upon the programmer. There is no path, schema, plan. You are your own boss. You decide. D is all about choice. Every time we start a new project, we need to decide what D subset to use. I find D similar to Gentoo philosophy-wise. Systemd vs OpenRC? Etc. I believe we need to somehow communicate this to the public to clarify all this confusion involved with D features.
Oct 10 2021
On Sun, Oct 10, 2021 at 09:54:11AM +0000, Ki Rill via Digitalmars-d wrote: [...]D is all about choice. Many people feel frustrated with D: safe, live, nogc, betterC, etc - what/when to use? They ultimately feel lost. But it's not a language thing. D lets the programmer make the choices and helps him stay true to what he has chosen. D is like C - it trusts the programmer, but it also has the necessary mechanisms to ensure that the programmer does not stray from the path chosen. Want to avoid the GC? Put nogc at the top of your file. Do you want your code to be safe? safe - is the way to go. Such mechanisms ensure you don't get lazy and start using the features you set to avoid. Unlike Rust, D does not enforce anything upon the programmer. There is no path, schema, plan. You are your own boss. You decide. D is all about choice. Every time we start a new project, we need to decide what D subset to use. I find D similar to Gentoo philosophy-wise. Systemd vs OpenRC? Etc. I believe we need to somehow communicate this to the public to clarify all this confusion involved with D features.+1, one of the things that drew me to D was the choices. It doesn't try to shove some idealogy down my throat, but gives me the tools to achieve what I want. Unlike some people here, I find that having more than one way to do something is a *good* thing. (When the choices are meaningful, that is. When there are multiple ways of doing something but the choices are not meaningful, that's a different question.) T -- "I'm not childish; I'm just in touch with the child within!" - RL
Oct 12 2021
On Tuesday, 12 October 2021 at 16:51:40 UTC, H. S. Teoh wrote:Unlike some people here, I find that having more than one way to do something is a *good* thing. (When the choices are meaningful, that is. When there are multiple ways of doing something but the choices are not meaningful, that's a different question.)It is not good when you have to read code written by others. Especially if it rarely used. (We can easily deal with "i++" and "i=i+1" because they occur frequently.) However, with meta-programming, people will write libraries that create N ways of doing the same thing. So not only do you need discipline when doing language design, but also when designing or choosing libraries, if you want to encourage people to write more readable code. Powerful meta-programming features like D/C++ provide also has some negative consequences. For larger long-lived programs, readable code often is on of the most important characteristic (in term of costs). In that regard, it might be desirable to use a language that is restrictive, but is geared towards the domain. I think the most well designed languages are designed for a specific use context, and that context guides the "values". Languages like D and C++ (and JavaScript) has not been designed for a specific context and the end result is a bit messy as a result. I am not sure if one can separate values and intended use context...
Oct 16 2021
On Monday, 4 October 2021 at 13:23:40 UTC, Paul Backus wrote:In ["Rust and Other Interesting Things"][1], Bryan Cantrill talks about the importance of a programming language's *values*. Values, he says, are the things a language *prioritizes*--the things it chooses when difficult tradeoffs have to be made. For example: everyone agrees that both "safety" and "performance" are valuable, but when forced to choose, some languages (Java, Python) are willing to trade away some performance for additional safety, whereas others (C, C++) would rather give up safety to gain performance. When we're choosing a programming language, Cantrill tells us, choosing one with the right *values* is just as important as choosing one with the right *features* and *ecosystem*--because values are what determine how those features and ecosystem will develop over time. One slide in his presentation contains a list of things that a programming language might value: Approachability Integrity Robustness Availability Maintainability Safety Compatibility Measurability Security Composability Operability Simplicity Debuggability Performance Stability Expressiveness Portability Thoroughness Extensibility Resiliency Transparency Interoperability Rigor Velocity I thought it might be fun to ask the D community: **which of the above values do you think are the most important to D? Choose no more than 5, and reply with your answer!** I've put my answer below, encoded using [ROT13][2]. Try to come up with your own answer before you read mine, to avoid biasing yourself. [1]: https://www.youtube.com/watch?v=2wZ1pCpJUIM [2]: https://rot13.com/ --- V guvax Q'f svir zbfg vzcbegnag inyhrf ner * Nccebnpunovyvgl - obgu Q'f flagnk naq ynathntr srngherf ner qrfvtarq gb or snzvyvne gb hfref bs bgure cbchyne ynathntrf (r.t., P, Wnin, Clguba, Wninfpevcg). gbhe.qynat.bet zragvbaf n "tenqhny yrneavat pheir" nf na rkcyvpvg qrfvta tbny. * Rkcerffvirarff - jvgu srngherf yvxr grzcyngrf, zvkvaf, naq bcrengbe bireybnqvat (vapyhqvat bcQvfcngpu), Q vf bar bs gur zbfg rkcerffvir ynathntrf guvf fvqr bs Yvfc. * Fnsrgl - abg whfg fnsr, ohg nyfb qrsnhyg vavgvnyvmngvba bs inevnoyrf, obhaqf-purpxvat sbe neenlf, rkprcgvbaf sbe reebe unaqyvat, naq ybgf bs bgure yvggyr qrpvfvbaf. * Cresbeznapr - angvir pbzcvyngvba, bs pbhefr, cyhf ybj-yriry srngherf yvxr enj cbvagref, vayvar nfz, naq ohvyg-va FVZQ bcrengvbaf. * Vagrebcrenovyvgl - abg bayl qbrf Q unir orfg-va-pynff P vagrebc, naq gur qvfgvapgvba bs orvat bar bs gur bayl ynathntrf gb rira *nggrzcg* P++ vagrebc, vg nyfb unf fhccbeg sbe Bowrpgvir-P pynffrf naq PBZ vagresnprf.I'm not an expert so I'm a little hesitant to post, but I'd say: Interoperability with C libraries - There are so many C libraries that do interesting things Performance - I like that the performance is reasonable, although I think most mainstream languages are getting there. Expressiveness - Any time I want to do something, from pointer based string functions to meta programming to multithreading via messaging, I find it in D. There is low mental friction. I also like that I can start with something not as strict and add strictness as I go. Free Nature - I like that it's future is not owned by Oracle, Apple or anyone like that. I also value the portability between windows and linux so I guess I'll make that number 5
Oct 30 2021