July 07, 2021

On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:

>

Inspiration from this r/C_Programming post

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 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 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.

July 07, 2021

On Wednesday, 7 July 2021 at 12:49:34 UTC, Paulo Pinto wrote:

>

Not really, in Java you can do it with annotation processors and compiler plugins at compile time, whereas in C# you can do it with code generators or T4 templates.

Good to know.

July 07, 2021
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.
July 09, 2021

On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:

>

Inspiration from this r/C_Programming post

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.

    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.

July 13, 2021
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 or C# their interface is remarkably close to solving the same 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)

You don't need this, C# has runtime reflection but there is 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.
July 19, 2021

On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:

>

Inspiration from this r/C_Programming post

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:

  1. If it's broken, it's usually faster to fix it yourself.

  2. If you put in the work, no one will stand in your way.

July 19, 2021

On Tuesday, 6 July 2021 at 20:53:12 UTC, Dylan Graham wrote:

>

Inspiration from this r/C_Programming post

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.

  1. 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.

1 2
Next ›   Last »