www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - What were some of your biggest breakthroughs while learning D?

reply Dylan Graham <dylan.graham2000 gmail.com> writes:
[Inspiration from this r/C_Programming 
post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

What's something you learnt or realised, a habit you developed, 
something you read or project you worked on that helped 
accelerate your understanding and/or productivity in D?

For example, mixin templates finally clicking and you realise how 
to use them in your code base. Stuff like that.
Jul 06
next sibling parent norm <norm.rowtree gmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?

 For example, mixin templates finally clicking and you realise 
 how to use them in your code base. Stuff like that.
D really did change how I approach programming tasks in any language. D templates with CTFE D syntax; `!` for templates, UFCS, optional parenthesis These features were a game changer for me because I could finally see through the syntax to semantics and I could easily create more fluent and monadic-like interfaces in my own code. C++ never had this clarity and for me personally it was always a muddy quagmire of Type\<typename T::SomeVector\<etc\<etc>>>. With a better understanding of templates I started thinking in terms of functional types instead of just values and data structures, which was universal to all programming languages, even dynamically typed languages like Python.
Jul 06
prev sibling next sibling parent reply SealabJaster <sealabjaster gmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 ...
How any combination of UFCS, dynamic code generation and introspection, shortened syntax for calling functions, the ability to pass lambdas to templates (which can also be completely inlined by the compiler without sacrificing on code readability), etc can all be used to create and model code almost exactly how you want it to. I very rarely feel constricted in D like I do in other languages. There's pros and cons to that of course, but when I feel like just tapping out something random, more often than not I can match the code model to my mental model. e.g. the very existence of UDAs can allow for pretty natural looking code: ```d Command("command", "This is a command that is totally super complicated.") struct ComplexCommand { CommandArgGroup("Debug", "Arguments related to debugging.") { CommandNamedArg("verbose|v", "Enables verbose logging.") Nullable!bool verbose; CommandNamedArg("log|l", "Specifies a log file to direct output to.") Nullable!string log; } } ``` (assume the same with JVM languages). However in C++ you probably have to do weird hacks or use an external tool. C is either the same as C++ or even worse. Another example would be ranges, which we all know about (taken from D's main page): ```d import std.stdio, std.array, std.algorithm; void main() { stdin .byLineCopy .array .sort!((a, b) => a > b) // descending order .each!writeln; } ``` Or maybe I want to design a UI system where, with a small bit of descriptive boiler plate, I can automatically enable new controls to be used within a UI definition file: ```d DataBinding struct MyControlBinding { BindingFor("stringVal") string someString; BindingFor("intVal") Name("number") int someInt; } UsesBinding!MyControlBinding class MyControl : UIBase { public string stringVal; public int intVal; } ``` ```sdlang UI:view { name "Some sexy custom UI" MyControl { someString "Hey" number 69 } } ``` Or literally even just simple things like custom error messages: ```d struct Vector(size_t dims) { static assert(dims <= 4, "The dimension is too large!") } ``` Then there's things like pegged, vibe-d's diet templates, etc... All of this is possible within a single language, using standard tooling. Once I learned about how to introspect code and to generate code, the amount of possibilities really opened up to me. D's expressiveness and modeling power is probably the biggest thing I'd say it has over most over languages. I feel even dynamic languages fail to do some of these things as elegantly.
Jul 06
next sibling parent SealabJaster <sealabjaster gmail.com> writes:
On Wednesday, 7 July 2021 at 00:13:44 UTC, SealabJaster wrote:
 ...
There's also cool shenanigans with things like this: https://dlang.org/blog/2017/02/13/a-new-import-idiom/
Jul 06
prev sibling parent reply Paulo Pinto <pjmlp progtools.org> writes:
On Wednesday, 7 July 2021 at 00:13:44 UTC, SealabJaster wrote:
 On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 ...
How any combination of UFCS, dynamic code generation and introspection, shortened syntax for calling functions, the ability to pass lambdas to templates (which can also be completely inlined by the compiler without sacrificing on code readability), etc can all be used to create and model code almost exactly how you want it to. I very rarely feel constricted in D like I do in other languages. There's pros and cons to that of course, but when I feel like just tapping out something random, more often than not I can match the code model to my mental model. e.g. the very existence of UDAs can allow for pretty natural looking code: ```d Command("command", "This is a command that is totally super complicated.") struct ComplexCommand { CommandArgGroup("Debug", "Arguments related to debugging.") { CommandNamedArg("verbose|v", "Enables verbose logging.") Nullable!bool verbose; CommandNamedArg("log|l", "Specifies a log file to direct output to.") Nullable!string log; } } ``` (assume the same with JVM languages).
Not really, in Java you can do it with annotation processors and with code generators or T4 templates.
Jul 07
parent SealabJaster <sealabjaster gmail.com> writes:
On Wednesday, 7 July 2021 at 12:49:34 UTC, Paulo Pinto wrote:
 Not really, in Java you can do it with annotation processors 

 it with code generators or T4 templates.
Good to know.
Jul 07
prev sibling next sibling parent Nicholas Wilson <iamthewilsonator hotmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?

 For example, mixin templates finally clicking and you realise 
 how to use them in your code base. Stuff like that.
UFCS + ranges made me how algorithms are supposed to compose You can make useful but really horrible interfaces (i.e. OpenCL) rather nice with reflection and CTFE
Jul 06
prev sibling next sibling parent reply Max Samukha <maxsamukha gmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?

 For example, mixin templates finally clicking and you realise 
 how to use them in your code base. Stuff like that.
For me, it is the indirect value I reaped by lurking in D's forums. There used to be some interesting discussions by language theorists that pushed me to learn and appreciate quite a bit of "abstract nonsense" and shown how many of what I thought was a cool new thing was just a hackish reincarnation of an old and well explored concept (including mixin templates).
Jul 07
parent Max Samukha <maxsamukha gmail.com> writes:
On Wednesday, 7 July 2021 at 08:41:05 UTC, Max Samukha wrote:

 shown
showed, etc I wish I could edit.
Jul 07
prev sibling next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/6/21 4:53 PM, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_big
est_breakthroughs/) 
 
 
 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped accelerate your 
 understanding and/or productivity in D?
 
 For example, mixin templates finally clicking and you realise how to use 
 them in your code base. Stuff like that.
Learning to not care about using the GC. Learning to have the compiler write code the way I would write it. vibe.d was immensely inspiring for this! -Steve
Jul 07
prev sibling next sibling parent Guillaume Piolat <first.name domain.tld> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?

 For example, mixin templates finally clicking and you realise 
 how to use them in your code base. Stuff like that.
- writing D explanations to solidify knowledge - using DUB and Semver really augmented the amount of software I could build, as you can maintain lazily - that led to learning to better isolate public APIs in order to stay topdown and reduce breakage - (minor) learning what the D GC actually does
Jul 07
prev sibling next sibling parent Dennis <dkorpel gmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?
- Arrays and Associative Arrays never need `null` checks. Their `null` state is equivalent to their empty state, so you can always safely insert elements or query their `.length`. In Java I commonly wrote `null` checks at the start of functions, I rarely need those in D. - Template arguments can be any compile-time known value. Coming from Java, I was used to seeing types in angle brackets `ArrayList<String>` which would be `ArrayList!string` in D, but D also allows `map!"a.x"` or `octal!10`. It took a while to get accustomed with that idea, but it makes templates very useful for other things than type polymorphism. - [UFCS](https://dlang.org/spec/function.html#pseudo-member) is not just syntactic sugar, but also enables certain generic code. E.g. an input range can define an `enum empty`, a variable `bool empty;`, or a function `bool empty() {...}`, and then you can access `.empty` on all of them. Other languages require parentheses for the function, or have the habit to capitalize constants ("EMPTY"). - This is not specific to D, but the [Git Lens VS Code extension](https://gitlens.amod.io/) is really useful when working on dmd/phobos/druntime. It immediately shows whether the code you're looking at was unchanged for 8 years or recently edited as part of a bug fix, and often helps to clear up why the code was written when there are no comments.
Jul 07
prev sibling next sibling parent Dukc <ajieskola gmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?
-That I have many lurking bugs in my code that end-to-end testing will never discover. I realized that in the first project where I unit tested in serious amounts. -That regardless of the above, I should not try to unit test everything. If a quality application is the aim, then sure I need to unit test most stuff before declaring 1.0. But premature optimization with reliability is almost as bad as with performance. -That it's good to document versions of the compiler, DUB and libraries I'm using. Even better is to use a reproducible build environment like Flatpak or Nix. -(this wasn't discovered while using D, but applies to D anyway) That it's definitely good to use version control for anything serious, even if I'm the only programmer! It does have a bit of learning curve, but it has a LOT of benefits. I don't necessarily need to have a cloud backup, using an USB stick as a backup repository works too. -That I should use a regular release of DMD compiler as a default -not the development build of DMD I happen to have last done. This applies to any part of D toolchain of course.
Jul 07
prev sibling next sibling parent Dylan Graham <dylan.graham2000 gmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?

 For example, mixin templates finally clicking and you realise 
 how to use them in your code base. Stuff like that.
- Mixin templates At first it looked like some weird template wizard magic, but I now use them often. I've found them to be phenomenal in promoting code reuse in classes and structs. They're the backbone for the CAN bus implementation in my projects. ```D mixin template canbusImpl(alias packetID) { enum id = packetID; static assert(id > 512 && id < 1024, "IDs must be between 512 and 1024!"); void read(const ubyte[] bytes) { // read bytes from the array to set the values of the encapsulating struct } void write(ubyte[] bytes) { // convert the encapsulating struct into a byte array } } struct HeartbeatPacket { mixin canbusImpl!10; ubyte deviceID; ubyte status; } struct DeviceErrorPacket { mixin canbusImpl!11; ubyte deviceID; ushort code; short recoveryMethod; } if(canbus.incomingData.id == HeartbeatPacket.id) { HeartbeatPacket h; h.read(canbus.incomingData.bytes); writeln(h.deviceID ~ " has a heartbeat!"); } ``` - UFCS At first I was nervous about using it (mostly because I didn't want to get it wrong then have to go back and debug it), but once I really delved into some examples with it I definitely appreciated the feature. I wish I had mentioned them in my article :( - Dlang Tour Despite feeling more confident in D, I do sometimes come back to the tour to refamiliarise myself with certain concepts. It works well to pick things up quickly.
Jul 09
prev sibling next sibling parent Jesse Phillips <Jesse.K.Phillips+D gmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?

 For example, mixin templates finally clicking and you realise 
 how to use them in your code base. Stuff like that.
I grew my skills with D, so there was not so much a jump in having new productivity. However there definitely are a few things that greatly influence how I design. * Ranges The sales pitch is mostly lost on me because if you look at Java problem. But their is one major difference, it is so much easier to build a Range in D rather than build the boilerplate in the other languages. But it gets more important, std.algorithms really demonstrates how important it is to have your algorithms be separated from storage. * CTFE (all the meta) something about having the ability to build out everything at Compile Time. D needs improvement here, but that doesn't mean other languages are nicer to work with. * Dynamic Typing I think the biggest benefit D provided me was that I never fell into the dynamic/duct typing trap. D types feel lightweight, you can change things, and most importantly the compiler yells at you for being inconsistent.
Jul 13
prev sibling next sibling parent Mathias LANG <geod24 gmail.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?

 For example, mixin templates finally clicking and you realise 
 how to use them in your code base. Stuff like that.
1) Not everything needs to be at compile time. It's perfectly fine to have your regexes initialized at program startup instead of having a bunch of ctRegex which will add 2 minutes of compilation time. 2) `immutable` is a special case, not the common case. `const` should be your default go-to keyword for attributes. 3) Simpler code is better. D gives you the tool to be very elaborate in your solution. Sometimes it's necessary, often it's not. The following are not D specific, but were learned while contributing: 4) If it's broken, it's usually faster to fix it yourself. 5) If you put in the work, no one will stand in your way.
Jul 18
prev sibling parent solidstate1991 <laszloszeremi outlook.com> writes:
On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:
 [Inspiration from this r/C_Programming 
 post](https://www.reddit.com/r/C_Programming/comments/oeoq82/what_were_some_of_your_biggest_breakthroughs/)

 What's something you learnt or realised, a habit you developed, 
 something you read or project you worked on that helped 
 accelerate your understanding and/or productivity in D?

 For example, mixin templates finally clicking and you realise 
 how to use them in your code base. Stuff like that.
1) Actually learning how to write code. Unfortunately in college, we were learned to "just follow orders of our higher ups", and often were discouraged from software optimization, with the claim that modern CPUs have many cores and stuff. 2) Learning that following a single programming paradigm isn't good. Prior to D, we mainly learned Object Oriented languages, and learned that that's the end of all things. We learned that "Aspect Oriented Programming" also exist, but that's all. When I started to write my own game engine, I did it in a strictly OOP sense, then, after it was unable to render more than one million pixels per seconds on my outdated PC, I decided to switch gears, and looked up a lot more things beyond what OOP could offer. First I've learned about Data-Oriented Design, which made me change so many things I immediately incremented the version number from 0.1 to 0.9 (biggest mistake). It was faster than before, so I looked even harder. I remembered a thing we learned, called SIMD, so I looked it up to utilize it for alpha-blending. I had to run a lot of circles with it, the initial assembly code I copied from the web had serious issues and otherwise everyone on the internet wanted to tell me the true gospel of OpenGL and shaders (which are nice and stuff, but couldn't do integer arithmetic easily, and not at all on older cards), then I needed to switch to using intel-intrinsics instead of using hard to maintain and seemingly easy to malfunction code. Then I learned some functional programming. I think many of its evangelists are quite irritating and think it'll replace everything, but it has its own place. Nowadays I started to label my functions with `const` whether its possible, so I won't get the possibility of a getter function writing unintentional data. :) It might have leaded to LDC2 better optimizing stuff in my engine by parallelization, with lead to a few confusing, hard to debug issues, that were resolved by using `synchronized`. While in many cases I had to give up the OOP parts, I managed to keep its modularity. However, sometimes I use function pointers or delegates instead of classes: similar kind of modularity, but often simpler. Using ` nogc` and `nothrow` helps a lot with performance, especially as I'm now forced to not allocate on the heap if possible. I'm at a point that with my knowledge and small team, I dared to begin to write a few simple software synths for it, which is quite fitting for a "retro-focused" game engine.
Jul 19