I just wish it had more popular traction - it's much better to program in than Rust, Go or even C# as a language, but the community support is lacking.
D is my favorite language, I enjoy using it a lot. Out of curiosity, when you say community support is lacking, what do you mean?
So far my experience has been that everyone in the community has been very helpful and eager to help when I've asked questions.
> when you say community support is lacking, what do you mean?
I look up how to do X, find very few resources, more than half mention D1. Compare that with looking up X in Rust or Python, how many mention Python 2 or Rust before the editions.
Came here to say exactly that. And despite my comment’s redundancy i’ll say it again. I love this language. Straight to the point, easy to learn, read and write. I wish it gained more traction.
I'm in the market for a new compiled language. Rust seems obstuse. I was toying with picking up Go but haven't committed yet. I want to write a Roguelike. I'm here and listening to you. Sell me on it.
In game communities, there are lots of developers who spend time inquiring and researching about game writing platforms (languages, libraries, engines) but end up writing nothing. So a developer expecting somebody to "sell" them a language in order to write a game, will likely end up writing nothing.
"Rust seems obstuse" doesn't mean anything. On the other hand, I personally think that Rust is not the most productive language, overall, for game development (I'm familiar with Rust gamedev). This consideration includes the hard truth that as of now, the game libraries are young and buggy.
In an theoretical world, where all the languages have stable and equally functional game libraries/engines, in my opinion, the most productive language is something with deterministic (manual) memory management, but less memory safety (=overhead) than Rust, but that is still safer than C-family languages. I can picture D fitting this characteristics, but also other modern languages. This does not apply to areas where where safety is paramount (e.g. networking).
When I say that Rust seems obtuse, I mean I've been bashing my head against its philosophy and syntax for some time without reaching the magic "hey this works and I'm suddenly productive" summit (or at least plateau).
I've come to the conclusion that it's not for me, but my interest in it stemmed from frustrations with Python and my memories of enjoying writing 'C' in the 90s. I find C++ a language without an underlying philosophy and seems like a horrid patchwork of things; Java is frustrating and verbose. C# is very Windows centric, which I'm not adverse to exactly, but I don't run it. Various other languages I've thought about and discarded.
I was toying with Go as that seems to have many fans, and seems to have wheels, but I'm cautious given some of the criticisms it comes under. D was not on my RADAR, but now I'm quite interested and probing its good and bad points. It looks promising on a casual look.
You're right, of course, "lots of developers who spend time inquiring and researching about game writing platforms (languages, libraries, engines) but end up writing nothing. "
Most people come from the point of view of they enjoy playing games, so they think they would enjoy writing them. Same with reading novels/writing them, and probably many other spheres of human creative endeavor.
I'm not saying I'm immune from this kind of thing, but my ideas are very modest, and if I fail to implement my game, no harm will come from it; the opposite in fact, as the very act of solving programming problems is as productive as solving a crossword puzzle, and will serve, if nothing else, to keep my mind sharp (as my current job requires no programming ability whatsoever).
I don't enjoy playing games, I'm tremendously bad at them and so don't get much positive re-inforcement on them as an enjoyable activity. But programming is fun, and that's what I'm looking for.
The Phobos/Tango thing has literally been settled for basically 10 to 13 years now.
Beyond that D is a good language for writing software in. all language communities have fractures unless the language attracts lots of either new or bad programmers who haven't formed opinions yet
If you're talking about the whole Tango/Phobos (2 std libs) thing, it's fixed and Phobos won. But now there are optional function attributes such as @nogc (checks that the code doesn't trigger the GC), @safe (memory safety checks) and nothrow that's causing a bit of a problem.
For example, not all libraries are @nogc. So if you want to use some library in your @nogc code and the library is not marked as @nogc, you can't use that library. This is not as bad as the two standard libraries problem but it restricts the libraries you can use.
The attributes are optional like I said, you can just ignore them and write code that uses the GC (not @nogc), code that is not explicitly checked by compiler for memory safety (not @safe) and code that throws exceptions (not nothrow).
Of course this is sort of expected in multi-paradigm languages, like some people disable C++ exceptions. But in D's case it feels like the compiler and library developers' efforts are spread thin.
The main issue with the nogc and nothrow flags is people taking a feature designed for careful consideration, and using them for building from-scratch code with often no philosophy other than a vague and usually completely unfounded mental model where GC == slow.
Agreed and I actually don't really care about the GC speed. I mostly use arenas / object pools and you can do that with or without GC.
Sort of undecided on the exceptions though. The Result / Option type in Rust is pretty nice to use (and !?*T in Zig, which is nicer if you ask me). It forces you to handle exceptions explicitly which is pretty nice and you can be sure there is no overhead introduced by the compiler for handling exception stuff.
I'd probably wrap all the exception throwing functions in my D codebases with Result type if we had language level support for sum types and match syntax. I know we have it in the standard library, I want it in the language with nicer syntax.
I also want the GC to be replaced with deterministic destruction using RC + ownership analysis and optimizations like Lobster does, but that's wishful thinking territory.
Even if it's small, the Option/Result style exceptions always have overhead in at least a limiting case whereas the unwinding style exceptions are basically zero cost with a modern compiler - the debt is paid in the implementation being tricky.
> unwinding style exceptions are basically zero cost with a modern compiler - the debt is paid in the implementation being tricky.
D doesn't return values when an exception is thrown as far as I know. How are exceptions' costs are paid by tricky implementation?
I thought exceptions require allocation and run-time type info and therefore always introduce some cost (this goes for D and C++). I guess returning values and allocating error strings statically can help with that (or maybe allocate some exception buffer on program start -- but that's technically "overhead"). Am I wrong, or missing some important context related to exceptions?
If you don't throw there's no overhead, hence Exception-al cases only. The Optional style always has an overhead but the cost of actually throwing is much less.
Lots of people do statically allocate their errors now.
Implementing stack unwinding properly is not trivial.
Agreed. @nogc is useful if you have no a disabled or no-runtime, or in tight loops. Other than that, it's more fruitful to use pools, benchmark the GC, keep scannable heap small.
It's crazier even when you consider how insanely fast the official D Forums render. I'm going to go out on a limb but I kind of doubt Vibe.d is plastered with @nogc everywhere. I am looking forward to the borrow checker being added to D on the other hand, that ought to be a little more interesting.
The official forums don't actually use vibe.d. vibe has the most marketing out of the D web frameworks, followed by hunt, but there's actually a few more too that just don't get as much attention, despite being older and possibly more widely used behind the scenes! The official forum uses the `ae` library. (And I have to mention my own `arsd` library which I'm pretty sure is the oldest web lib - mine dates back to 2008, but ae's pretty old too so he might beat me, and mine actually does better on some benchmarks despite me using GC and such with wild abandon.)
That said though, yeah, I don't think any of them use `@nogc`. I've actually tried to get the gc to interrupt audio code before and couldn't even hear it. I'm sure a bigger heap to scan might cause a problem in some situations, but these fears are really overblown in the popular commentariat.
Parts of it are `@nogc`, not all of it. You'd have to check the documentation for each function you want to use (or write `@nogc` code that uses the std and see if the compiler complains I guess).
I played with D quite a bit, and really liked its syntax, perhaps apart from the fact that you start with the type in declarations, which IMO is a bit detrimental to visual scannability.
Anyways, the strong concurrency story in Go finally bought me over there though.
I still miss the super readable (almost python-like) syntax from D though.
I quite prefer types on the left. The name of a variable expresses hope about its use and purpose, but the type is a definite statement about what the behaviour of the object is. I've used both and really prefer left types.
Out of all the new shiny low-level languages, people seem to praise its strong compile-time metaprogramming facilities. Though the compile-time execution engine in D is still a tree-walk interpreter (very bad performance/memory usage), unlike in Nim and Jai where they use a much faster bytecode interpreter for the evaluation.
The compile time execution itself is just one piece of the puzzle, the other two being compile time reflection (which I think is actually the key piece) and the built in code generation.
Running functions alone is not that interesting, and neither really is generating code. You can do those (arguably better for some cases) with helper programs as a separate build step. But reflection is non-trivial to do externally, so that's the biggest value add, and using it with all three pieces let you close the loop.
Agree with this, Zig and Jai seems to be the most ergonomic in this area (types can be checked and manipulated in compile time as easy as values in runtime).
But what I’ve mentioned is also very related to the ergonomics of compile-time metaprogramming, since these techniques are all useless if it severely increases builds times up to the point that developers have to use it sparingly. Only Nim and Jai has fully gone the route of using a bytecode VM for compile-time evaluation, while D had a similar project back in 2017 that was abandoned, and for other languages (C++, Zig, etc.) it’s still in the planning stage.
Unlike some D programmers I don't mind rust but compared to C and C++ the primary difference I'd say is that D has a lot of features that you'd have to emulate with either macros or recursive templates that means that the source files end up much cleaner.
If you want to declare a struct with N members where N is declared at compile time, in C++ it's usually a question of doing a bunch of compile time magic that leaves a roadside picnic of SFINAE everywhere whereas in D it's just a "static foreach" loop inside a template.
I've been using D for my amateur game engine development for a while now and so far it's been a pretty good experience.
Thanks to reflection features I can serialize/deserialize entire scenes just by annotating the fields in structures as needed, and can also autogenerate editor fields for inspector views. With C++ I'd have to do some out of place looking define magic to generate my structures and it wouldn't just work with any struct.
Unlike my fellow D game developers I don't fight the GC. I don't use any of the @nogc features in D or obsess about manual memory management. I have a fairly beefy machine, but still, I think the dangers of D's GC are somewhat overblown. There was a blog article back in the day by someone writing a 3D space game in D and it was often referred to as an example of how bad D's GC is, but there wasn't really enough data in that post to know about the methodology. Firstly, in a game most of the data should be preallocated anyway, in the game loop there isn't that much to allocate. Secondly, D has value types, so there's much less pressure on GC because you can stack allocate things like vectors or matrices. Sure, in other GC languages a sufficiently smart VM could probably optimize that out and avoid the GC, but I doubt it would catch most cases.
I also like how easy it is to interact with C. This grants me access to gamedev libraries such as bgfx, wgpu-native, ODE, NewtonPhysics and many, many more. C++ interaction however never cared much for. I feel like D spent too much effort here, even adding language features (copy constructors) to interact better with C++. In the meantime, it seems that it's still hard to interact with C++ libraries from D, and ironically I feel like languages like Rust or Zig have a better interop story with popular C++ libraries like Qt or Bullet, despite not investing as heavily into that.
My main current issue with D is that as a community project, it seems to lack some direction. There's some very talented people working around the project, but most of that work is done on a specific issues and projects people want to work on. Since a lot of the work on D is unpaid work, you can't force people to do what you want them to do. However, the language lead team should influence the direction of the language and provide a path forward. It's getting better in recent times, so there is a lot to look for in that aspect.
The multiparadigm aspect of D and its flexibility can be detrimental too sometimes. There are some subgroups in the language community that approach the language in a specific way and feel their way is the true "D way". For example, you have OOP folks that would like more features like named constructors, you have template metaprogramming folks who would like to remove most D features such as classes and just replace them with some metaprogramming template magic, you have folks that disable the GC and avoid the standard library from the get-go. This causes some friction, because any new feature for the language would have some opposition from the other side who will consider it bloat and unnecessary. In some ways the article about "Lisp curse" applies well to D.
These factors however don't really influence me personally, because I get to pick the features I want to use and can avoid the ones that I don't see the benefit of.
LDC does a fairly good job of removing brain-dead GC allocations (mainly for closures).
As for style, we have very few issues getting non-D programmers writing D. They don't know the fancy stuff exists until we tell them when they need it.
The lack of the direction is definitly the biggest issue, as every couple of years the next big thing that will finally bring the crowds to D gets started, without fully finalizing the previous one.
These distractions have allowed competition to come up, and C++, Java and C# to strengthen their position by improving in areas of metaprogramming, modules, type inference and AOT compilation, making the transition to a smaller ecosystem less appealing, just to use such features.
I recently noticed that Andrei Alexandrescu is at NVidia now, and I imagine that most likely he will continue focused on C++ instead, or maybe NVidia is going to add D to CUDA?
I don't know, it is a pity, because the community is great.
Shameless plug: LDC (the LLVM based D compiler) can already target CUDA (and OpenCL) and wraps its API and all of the nasty details involved in replicating <<<>>> kernel launches with https://github.com/libmir/dcompute/ with a sane syntax that's type safe. LLVM handles the codegen, and all of the "magic" is done in the library.
I think having an OOTB standard library that kind of targets production ready functionalities like Golang does would definitely be the real game changer for me. With Go I can do everything leading up to using a database driver for web dev without installing a single external dependency. I know D has Vibe.d but Go has net/http which is production tier.
Don't make me work to build something by forcing me to research every piece of it. You can do all sorts of things in Go out of the box that get you building production tier work right away.
D has one of the best/most-mature C++-interop stories around. You can't talk to everything but the GCC and LLVM backends rely extensively on D producing correct C++ classes and vtables.
Some months ago i started making a new game engine in Free Pascal[0]. D however was the language i considered the most of all alternatives due to its fast build times (at least for DMD) and metaprogramming and compile time function evaluation and code generation abilities that would help a lot to minimize boilerplate and automate things. In fact i chose FPC less for the language and more for other reasons - as a language i think D would fit better.
The two main reasons i chose Free Pascal are (both of which are important):
1. There is a strong aversion to breaking working code in FPC which to some extent is also part of the overall ecosystem. Code i wrote 20 years ago still compiles because any new features are made so that they don't break existing code. Exceptions exist, like when how string are handled changed, but that was a quick fix (in all of my programs i only had to apply a single line fix twice).
I don't know D's story on that but i've heard that there were updates to the D compiler that broke code (but i don't know how severe that is - FPC also introduced theoretically breaking code almost every version but in practice it is usually extreme edge cases, compiler bugs or very internal things and these latter only change like per decade or so).
In general i want code that i know it worked today to keep working in 10 years from today so i can focus on other things instead of babysitting it (i do copy/paste code i know that works from my existing projects all the time - even the engine i linked above contains a lot of code from older projects, the earliest bits being from 2007 or 2008).
This is even more important if i decide to switch to a new language because i wouldn't be able to use much of my existing code so any new code i write i want it to be valid for years ahead.
2. Lazarus and LCL. Think open source Delphi or Visual Basic with a real framework and a strong language. Lazarus is a "real" IDE in that it isn't just a glorified text editor attached to a compiler but it knows the language and builds a database of the entire project in memory, which allows for it to manipulate the code for you (this avoids a lot of boilerplate that come out of the verbose syntax Free Pascal has). More importantly it provides a WYSIWYG visual editor for GUIs (very important for tools) and a rich application framework (LCL) that is designed around Lazarus - these aren't independent bits someone stuck together with some glue, they are all made with each other in mind, which provides a more coherent experience than if someone stitched things together (if anything most of the issues Lazarus/LCL has is from things outside of their control, like the backend GUI toolkits). I have used a lot of other GUI approaches, Lazarus beats them all hands down. And as a cherry on top Lazarus is a native app written in Free Pascal itself and is very responsive - it even runs on older Rasberry Pis with relatively low resource requirements.
Sadly D doesn't seem to have a decent GUI story, let alone something like Lazarus and LCL. A promising library was dlangui[1], but that is a 3rd party library that looks like the author decided to abandon[2]. Honestly IMO without something that is adopted by the core D developers (and by extension the rest of the D community) i can't see anything flourishing there - it'll instead be a bunch of independent solo devs making their own half-baked stuff for eternity (btw, yes, Lazarus/LCL are technically a separate project but in practice there is strong overlap between the two projects' developers and they share resources). At best you get bindings to Gtk+ but that has its own share of issues and bindings to other toolkits (e.g. wxWidgets) look abandoned.
I occasionally check out D to see what is the status wrt the above but for years things do not seem to change. I do hope that at some point D will have a good GUI application framework and a good native IDE that understands the language itself.
> There is a strong aversion to breaking working code
Am I the only person who doesn't view this as a good thing? If you want to compile code your wrote 20 years ago, use a compiler version from 20 years ago. Forcing backwards compatability hinders a languages growth and forces it to stick by decisions that, in hindsight, may not have been the best.
Reconstructing an obsolete toolchain is a nightmare.
I think it's great that there are languages like FreePascal, C, and Common Lisp, which make an effort to think in terms of decades. The existence of these languages frees everyone else up to break compatibility when they want to, because projects which need strong stability guarantees can chose these languages for that project.
> If you want to compile code your wrote 20 years ago, use a compiler version from 20 years ago.
I want to compile code i wrote 20 years ago alongside code i wrote 10 years ago and yesterday, not just compile some old project. Though even compiling some old project should be as friction free as possible too.
The point is that once i write some code that i know works, it should keep working in future versions so i wont have to worry about updates (which is now the case with both Free Pascal and Lazarus/LCL - i even use the development versions directly from the repository).
> Forcing backwards compatability hinders a languages growth and forces it to stick by decisions that, in hindsight, may not have been the best.
And ignoring backwards compatibility forces all users of the language (which unless it is a toy project, are way more numerous than the developers of the language) to waste time keeping their projects up to date instead of working on new features and/or bugfixes for their projects.
Also Free Pascal does have a way to avoid this (to some extent) using modes and modeswitches - the former affect the Pascal dialect being used for a file (which can be mixed with other files with other modes) and the latter enable/alter syntactical features that would otherwise break existing code, thus allowing it to be improved piecemeal without breaking anything else.
AFAIK similar features exist for some other languages (i remember reading that Rust's epochs are meant to do something like that though i don't know if files from multiple epochs can be mixed).
(Rust’s epochs we’re renamed “editions” before release. They’re per package, not per file. Projects can use packages from any edition, but all files in a given package have the same edition. This is at least partially because “file” is not really a coherent boundary in Rust.)
It's very interesting that you're using Free Pascal because this ship design company (SARC) has written a replacement of legacy Pascal compiler in D language for their existing simulator codes [1],[2],[3].
Free Pascal was actually on the shortlist of SARC, together with Ada and D [1]. We had different requirements though: GUI was not an issue as we have our own GUI; neither was an IDE. What was very important in our case was D’s compile time reflection capabilities which has enabled us to implement (de)serialisation to/from the binary format that the old Pascal implementation produced. In the maritime industries it is important to be able to build on projects that were developed in the past.
Pascal is not a bad language for engineering, in some aspects it is even better than D. Still, the combined features of D made it a winner over all, in our case.
What is its level of maturity on non x86 platforms such as ARM? It might be a nice alternative to C and especially C++ on small embedded boards, but then any smaller overhead would matter a lot more than on a PC.
Fully operational. On arm/linux it is trivially easy to use, tends to just work out of the box (ldc offers packaged downloads on their website, gdc is in the Raspbian repository, etc). If you are doing bare metal and/or strictly limited hardware resources it is a little more work to be productive with minimal runtime but still not hard if you're familiar with how to do it.
I learned D and then solved Advent Of Code 2019 with it.
Like other people above, I really liked the language, and I wish could use it at work. For me it hit a good spot midway between C# and C++. The documentation was complete enough for me. Although IMO AOC isn't representative of "real world" programming.
Regarding the GC, I had no major problems with it, but when faced with frequent allocations it performed slightly worse than what I'm used to from C#, in terms of memory consumption. In C# code, in places where I'm not concerned with performance, I'm used to allocate many small and temporary dictionaries freely without a hitch, the dotnet GC does a great job of releasing them as I go along.
In D however I wrote code using the same style (allocating relatively small temporary dictionaries in a loop) and saw memory usage ballooning very quickly, to several GBs.
At the end the intended solution for the AOC problem shouldn't have involved this many allocations anyway, so I didn't spend time investigating this too deeply.
Small dynamic arrays did not cause this problem, though, as far as I remember, the GC seemed to collect them well enough.
I absolutely adore D and have used it for years, including publishing software.
However, the community is just too small (which has several consequences, including lack of packages, web frameworks, etc.), and for serious projects that I want to move to commercialization, I had to move to Rust.
62 comments
[ 2.8 ms ] story [ 137 ms ] threadI just wish it had more popular traction - it's much better to program in than Rust, Go or even C# as a language, but the community support is lacking.
I look up how to do X, find very few resources, more than half mention D1. Compare that with looking up X in Rust or Python, how many mention Python 2 or Rust before the editions.
You can start your D usage with these examples: https://github.com/p0nce/DIID
I don't know the status of https://code.dlang.org/packages/libtcod-d
https://github.com/munificent/hauberk
https://journal.stuffwithstuff.com/category/roguelike/
"Rust seems obstuse" doesn't mean anything. On the other hand, I personally think that Rust is not the most productive language, overall, for game development (I'm familiar with Rust gamedev). This consideration includes the hard truth that as of now, the game libraries are young and buggy.
In an theoretical world, where all the languages have stable and equally functional game libraries/engines, in my opinion, the most productive language is something with deterministic (manual) memory management, but less memory safety (=overhead) than Rust, but that is still safer than C-family languages. I can picture D fitting this characteristics, but also other modern languages. This does not apply to areas where where safety is paramount (e.g. networking).
When I say that Rust seems obtuse, I mean I've been bashing my head against its philosophy and syntax for some time without reaching the magic "hey this works and I'm suddenly productive" summit (or at least plateau).
I've come to the conclusion that it's not for me, but my interest in it stemmed from frustrations with Python and my memories of enjoying writing 'C' in the 90s. I find C++ a language without an underlying philosophy and seems like a horrid patchwork of things; Java is frustrating and verbose. C# is very Windows centric, which I'm not adverse to exactly, but I don't run it. Various other languages I've thought about and discarded.
I was toying with Go as that seems to have many fans, and seems to have wheels, but I'm cautious given some of the criticisms it comes under. D was not on my RADAR, but now I'm quite interested and probing its good and bad points. It looks promising on a casual look.
You're right, of course, "lots of developers who spend time inquiring and researching about game writing platforms (languages, libraries, engines) but end up writing nothing. "
Most people come from the point of view of they enjoy playing games, so they think they would enjoy writing them. Same with reading novels/writing them, and probably many other spheres of human creative endeavor.
I'm not saying I'm immune from this kind of thing, but my ideas are very modest, and if I fail to implement my game, no harm will come from it; the opposite in fact, as the very act of solving programming problems is as productive as solving a crossword puzzle, and will serve, if nothing else, to keep my mind sharp (as my current job requires no programming ability whatsoever).
I don't enjoy playing games, I'm tremendously bad at them and so don't get much positive re-inforcement on them as an enjoyable activity. But programming is fun, and that's what I'm looking for.
Will definitely revisit when things settle.
Beyond that D is a good language for writing software in. all language communities have fractures unless the language attracts lots of either new or bad programmers who haven't formed opinions yet
If you're talking about the whole Tango/Phobos (2 std libs) thing, it's fixed and Phobos won. But now there are optional function attributes such as @nogc (checks that the code doesn't trigger the GC), @safe (memory safety checks) and nothrow that's causing a bit of a problem.
For example, not all libraries are @nogc. So if you want to use some library in your @nogc code and the library is not marked as @nogc, you can't use that library. This is not as bad as the two standard libraries problem but it restricts the libraries you can use.
The attributes are optional like I said, you can just ignore them and write code that uses the GC (not @nogc), code that is not explicitly checked by compiler for memory safety (not @safe) and code that throws exceptions (not nothrow).
Of course this is sort of expected in multi-paradigm languages, like some people disable C++ exceptions. But in D's case it feels like the compiler and library developers' efforts are spread thin.
Write the code first then measure it.
Sort of undecided on the exceptions though. The Result / Option type in Rust is pretty nice to use (and !?*T in Zig, which is nicer if you ask me). It forces you to handle exceptions explicitly which is pretty nice and you can be sure there is no overhead introduced by the compiler for handling exception stuff.
I'd probably wrap all the exception throwing functions in my D codebases with Result type if we had language level support for sum types and match syntax. I know we have it in the standard library, I want it in the language with nicer syntax.
I also want the GC to be replaced with deterministic destruction using RC + ownership analysis and optimizations like Lobster does, but that's wishful thinking territory.
D doesn't return values when an exception is thrown as far as I know. How are exceptions' costs are paid by tricky implementation?
I thought exceptions require allocation and run-time type info and therefore always introduce some cost (this goes for D and C++). I guess returning values and allocating error strings statically can help with that (or maybe allocate some exception buffer on program start -- but that's technically "overhead"). Am I wrong, or missing some important context related to exceptions?
Lots of people do statically allocate their errors now.
Implementing stack unwinding properly is not trivial.
That said though, yeah, I don't think any of them use `@nogc`. I've actually tried to get the gc to interrupt audio code before and couldn't even hear it. I'm sure a bigger heap to scan might cause a problem in some situations, but these fears are really overblown in the popular commentariat.
Anyways, the strong concurrency story in Go finally bought me over there though.
I still miss the super readable (almost python-like) syntax from D though.
Running functions alone is not that interesting, and neither really is generating code. You can do those (arguably better for some cases) with helper programs as a separate build step. But reflection is non-trivial to do externally, so that's the biggest value add, and using it with all three pieces let you close the loop.
But what I’ve mentioned is also very related to the ergonomics of compile-time metaprogramming, since these techniques are all useless if it severely increases builds times up to the point that developers have to use it sparingly. Only Nim and Jai has fully gone the route of using a bytecode VM for compile-time evaluation, while D had a similar project back in 2017 that was abandoned, and for other languages (C++, Zig, etc.) it’s still in the planning stage.
Unlike some D programmers I don't mind rust but compared to C and C++ the primary difference I'd say is that D has a lot of features that you'd have to emulate with either macros or recursive templates that means that the source files end up much cleaner.
If you want to declare a struct with N members where N is declared at compile time, in C++ it's usually a question of doing a bunch of compile time magic that leaves a roadside picnic of SFINAE everywhere whereas in D it's just a "static foreach" loop inside a template.
Thanks to reflection features I can serialize/deserialize entire scenes just by annotating the fields in structures as needed, and can also autogenerate editor fields for inspector views. With C++ I'd have to do some out of place looking define magic to generate my structures and it wouldn't just work with any struct.
Unlike my fellow D game developers I don't fight the GC. I don't use any of the @nogc features in D or obsess about manual memory management. I have a fairly beefy machine, but still, I think the dangers of D's GC are somewhat overblown. There was a blog article back in the day by someone writing a 3D space game in D and it was often referred to as an example of how bad D's GC is, but there wasn't really enough data in that post to know about the methodology. Firstly, in a game most of the data should be preallocated anyway, in the game loop there isn't that much to allocate. Secondly, D has value types, so there's much less pressure on GC because you can stack allocate things like vectors or matrices. Sure, in other GC languages a sufficiently smart VM could probably optimize that out and avoid the GC, but I doubt it would catch most cases.
I also like how easy it is to interact with C. This grants me access to gamedev libraries such as bgfx, wgpu-native, ODE, NewtonPhysics and many, many more. C++ interaction however never cared much for. I feel like D spent too much effort here, even adding language features (copy constructors) to interact better with C++. In the meantime, it seems that it's still hard to interact with C++ libraries from D, and ironically I feel like languages like Rust or Zig have a better interop story with popular C++ libraries like Qt or Bullet, despite not investing as heavily into that.
My main current issue with D is that as a community project, it seems to lack some direction. There's some very talented people working around the project, but most of that work is done on a specific issues and projects people want to work on. Since a lot of the work on D is unpaid work, you can't force people to do what you want them to do. However, the language lead team should influence the direction of the language and provide a path forward. It's getting better in recent times, so there is a lot to look for in that aspect.
The multiparadigm aspect of D and its flexibility can be detrimental too sometimes. There are some subgroups in the language community that approach the language in a specific way and feel their way is the true "D way". For example, you have OOP folks that would like more features like named constructors, you have template metaprogramming folks who would like to remove most D features such as classes and just replace them with some metaprogramming template magic, you have folks that disable the GC and avoid the standard library from the get-go. This causes some friction, because any new feature for the language would have some opposition from the other side who will consider it bloat and unnecessary. In some ways the article about "Lisp curse" applies well to D.
These factors however don't really influence me personally, because I get to pick the features I want to use and can avoid the ones that I don't see the benefit of.
As for style, we have very few issues getting non-D programmers writing D. They don't know the fancy stuff exists until we tell them when they need it.
These distractions have allowed competition to come up, and C++, Java and C# to strengthen their position by improving in areas of metaprogramming, modules, type inference and AOT compilation, making the transition to a smaller ecosystem less appealing, just to use such features.
I recently noticed that Andrei Alexandrescu is at NVidia now, and I imagine that most likely he will continue focused on C++ instead, or maybe NVidia is going to add D to CUDA?
I don't know, it is a pity, because the community is great.
Don't make me work to build something by forcing me to research every piece of it. You can do all sorts of things in Go out of the box that get you building production tier work right away.
You can catch C++ exceptions
The two main reasons i chose Free Pascal are (both of which are important):
1. There is a strong aversion to breaking working code in FPC which to some extent is also part of the overall ecosystem. Code i wrote 20 years ago still compiles because any new features are made so that they don't break existing code. Exceptions exist, like when how string are handled changed, but that was a quick fix (in all of my programs i only had to apply a single line fix twice).
I don't know D's story on that but i've heard that there were updates to the D compiler that broke code (but i don't know how severe that is - FPC also introduced theoretically breaking code almost every version but in practice it is usually extreme edge cases, compiler bugs or very internal things and these latter only change like per decade or so).
In general i want code that i know it worked today to keep working in 10 years from today so i can focus on other things instead of babysitting it (i do copy/paste code i know that works from my existing projects all the time - even the engine i linked above contains a lot of code from older projects, the earliest bits being from 2007 or 2008).
This is even more important if i decide to switch to a new language because i wouldn't be able to use much of my existing code so any new code i write i want it to be valid for years ahead.
2. Lazarus and LCL. Think open source Delphi or Visual Basic with a real framework and a strong language. Lazarus is a "real" IDE in that it isn't just a glorified text editor attached to a compiler but it knows the language and builds a database of the entire project in memory, which allows for it to manipulate the code for you (this avoids a lot of boilerplate that come out of the verbose syntax Free Pascal has). More importantly it provides a WYSIWYG visual editor for GUIs (very important for tools) and a rich application framework (LCL) that is designed around Lazarus - these aren't independent bits someone stuck together with some glue, they are all made with each other in mind, which provides a more coherent experience than if someone stitched things together (if anything most of the issues Lazarus/LCL has is from things outside of their control, like the backend GUI toolkits). I have used a lot of other GUI approaches, Lazarus beats them all hands down. And as a cherry on top Lazarus is a native app written in Free Pascal itself and is very responsive - it even runs on older Rasberry Pis with relatively low resource requirements.
Sadly D doesn't seem to have a decent GUI story, let alone something like Lazarus and LCL. A promising library was dlangui[1], but that is a 3rd party library that looks like the author decided to abandon[2]. Honestly IMO without something that is adopted by the core D developers (and by extension the rest of the D community) i can't see anything flourishing there - it'll instead be a bunch of independent solo devs making their own half-baked stuff for eternity (btw, yes, Lazarus/LCL are technically a separate project but in practice there is strong overlap between the two projects' developers and they share resources). At best you get bindings to Gtk+ but that has its own share of issues and bindings to other toolkits (e.g. wxWidgets) look abandoned.
I occasionally check out D to see what is the status wrt the above but for years things do not seem to change. I do hope that at some point D will have a good GUI application framework and a good native IDE that understands the language itself.
[0] CodeSgt ↗ > There is a strong aversion to breaking working code samatman ↗ Reconstructing an obsolete toolchain is a nightmare. badsectoracula ↗ > If you want to compile code your wrote 20 years ago, use a compiler version from 20 years ago. steveklabnik ↗ (Rust’s epochs we’re renamed “editions” before release. They’re per package, not per file. Projects can use packages from any edition, but all files in a given package have the same edition. This is at least partially because “file” is not really a coherent boundary in Rust.) schveiguy ↗ dlangui and dlangide has been adopted by GrimMaple (who is on the D discord as well), and is actively being developed. teleforce ↗ It's very interesting that you're using Free Pascal because this ship design company (SARC) has written a replacement of legacy Pascal compiler in D language for their existing simulator codes [1],[2],[3]. _veelo ↗ Free Pascal was actually on the shortlist of SARC, together with Ada and D [1]. We had different requirements though: GUI was not an issue as we have our own GUI; neither was an IDE. What was very important in our case was D’s compile time reflection capabilities which has enabled us to implement (de)serialisation to/from the binary format that the old Pascal implementation produced. In the maritime industries it is important to be able to build on projects that were developed in the past.
Am I the only person who doesn't view this as a good thing? If you want to compile code your wrote 20 years ago, use a compiler version from 20 years ago. Forcing backwards compatability hinders a languages growth and forces it to stick by decisions that, in hindsight, may not have been the best.
I think it's great that there are languages like FreePascal, C, and Common Lisp, which make an effort to think in terms of decades. The existence of these languages frees everyone else up to break compatibility when they want to, because projects which need strong stability guarantees can chose these languages for that project.
I want to compile code i wrote 20 years ago alongside code i wrote 10 years ago and yesterday, not just compile some old project. Though even compiling some old project should be as friction free as possible too.
The point is that once i write some code that i know works, it should keep working in future versions so i wont have to worry about updates (which is now the case with both Free Pascal and Lazarus/LCL - i even use the development versions directly from the repository).
> Forcing backwards compatability hinders a languages growth and forces it to stick by decisions that, in hindsight, may not have been the best.
And ignoring backwards compatibility forces all users of the language (which unless it is a toy project, are way more numerous than the developers of the language) to waste time keeping their projects up to date instead of working on new features and/or bugfixes for their projects.
Also Free Pascal does have a way to avoid this (to some extent) using modes and modeswitches - the former affect the Pascal dialect being used for a file (which can be mixed with other files with other modes) and the latter enable/alter syntactical features that would otherwise break existing code, thus allowing it to be improved piecemeal without breaking anything else.
AFAIK similar features exist for some other languages (i remember reading that Rust's epochs are meant to do something like that though i don't know if files from multiple epochs can be mixed).
[1]https://www.sarc.nl/
[2]Extending Pegged to Parse Another Programming Language:
https://youtu.be/NoAJziYZ4qs
[3]Transcompilation into D:
https://youtu.be/HvunD0ZJqiA
Pascal is not a bad language for engineering, in some aspects it is even better than D. Still, the combined features of D made it a winner over all, in our case.
[1] https://dlang.org/blog/2018/06/20/how-an-engineering-company...
Like other people above, I really liked the language, and I wish could use it at work. For me it hit a good spot midway between C# and C++. The documentation was complete enough for me. Although IMO AOC isn't representative of "real world" programming.
Regarding the GC, I had no major problems with it, but when faced with frequent allocations it performed slightly worse than what I'm used to from C#, in terms of memory consumption. In C# code, in places where I'm not concerned with performance, I'm used to allocate many small and temporary dictionaries freely without a hitch, the dotnet GC does a great job of releasing them as I go along.
In D however I wrote code using the same style (allocating relatively small temporary dictionaries in a loop) and saw memory usage ballooning very quickly, to several GBs.
At the end the intended solution for the AOC problem shouldn't have involved this many allocations anyway, so I didn't spend time investigating this too deeply.
Small dynamic arrays did not cause this problem, though, as far as I remember, the GC seemed to collect them well enough.
However, the community is just too small (which has several consequences, including lack of packages, web frameworks, etc.), and for serious projects that I want to move to commercialization, I had to move to Rust.