This is what I love HN for. Every now and then there's a submission like this that makes me go: "How do you even...".
That being said, is there maybe somewhere a more thorough write-up about the whole thing? You know, with more in-depth technical details, gotchas, and so on? I'm sure many people would enjoy reading that!
Sorry, no. I don't have a blog or website or anything. The closest thing I have to a devlog are some posts in a private Facebook group dedicated to the Holden Commodore.
This project sounds awesome. I hope you will find some time later to post it on the web. So much legendary information is stuck in Facebook, and difficult to find, or just lost forever.
What are the legal hurdles you had to jump to get this hack approved for street use? As car modders know all too well, this can often be the hardest task.
I follow the car modding scene and to be honest, in the U.S. there don't seem to be anything preventing this from being street legal.
Even in California, something like this being a non-engine mod I don't see it being an issue.
Agree. If you start messing with the engine, and heaven help you, emission related equipment, you are going to have a long journey, and a lot of bumps along the way. Anything else? Pretty much, have at it.
The approval I got from the engineer was due to the following points:
1. The 6 speed came out of a newer generation of the model.
2. My controller has some safety features.
3. My controller emulates factory hydraulic behaviour. Had I implemented something like a transbrake, I would have been in for a very long ride of red tape.
Firstly, Congratulations. This is no trivial accomplishment. Here are the questions I have.
1. Normally, cars come with their own ECUs for the engine. Interfacing with them requires knowledge about the underlying firmware used afaik. Did you happen to reverse engineer the firmware so that you could interface your own electronics with the provided ECU ?
2. How did you make the car believe that your 6 speed automatic transmission was a 4 speed automatic ?
3. > "the ability to go ahead and change the way it works whenever I want." - Could you please elaborate what you mean by this ?
Again, I am amazed by what you have accomplished. My inner mechanical engineer is so keen to know how this all came together. I think everyone would definitely appreciate if you could provide a rough overview of how you achieved these things. Thank you :)
1. I don't interface to my car's electronics over serial or CAN bus. Instead, I interface by emulating actuators and sensors the 4 speed gearbox computer expects.
2. I'd like to introduce you to "manualisation" [0]. It's where the solenoids of the 4 speed are wired directly to the gear selector switch. The 4 speed computer is surprisingly tolerant of this, and it forms the basis of my interface.
My interface provides enough information to the 4 speed computer to stop it from erroring out or putting my car into limp mode. However, it is aware that something has changed because changes in engine RPM do not correlate with its shift commands.
3. I mean in terms of software. I can modify the behaviour of my box more than a standard tune can. I can add a 0-100KM/h tracker to my system, or shift lights, I can fundamentally change the decision making process in shifting (for the moment it's torque based), etc.
I could go out on a limb and a GPS module and a map; it'd select a gear based on the corner angle and speed or so.
Thank you for kind words :) If you have any other questions, ask away!
Thank you for your reply. That is quite enlightening. I am quite surprised that the Transmission Control Unit(TCU) is tolerant of the solenoid modification. However, I have two questions though.
1. So based on my understanding, engine speed sensor readings are sent to the TCU which in turn regulates the solenoids(There might be other sensors as well but for my question, I think they aren't that important). So in order for your modification to work, you have to get these CAN frames, understand the reading, regulate your 6 speed auto gearbox and then create a CAN frame that would imitate the sensors of the 4 speed auto gearbox(to basically tell the TCU that the gearbox has been regulated correctly). You can in principle neglect the actuator commands that are sent by the TCU to the solenoids since you are regulating it on your own. However, in order to do this, you have to understand the CAN frames being used and also the protocol used(address based or message based). How did you figure this out ? Or is my understanding wrong here ?
2. Did you use FreeRTOS for your STM32F407 component ?
I really appreciate you taking the time to answer the questions :)
I was quite surprised, too. Maybe it was a little gift from Holden to the burnout bogans?
1. My apologies, I've confused you. CAN communications are purely internal for my system, it doesn't communicate via CAN to the car's computers.
The sensors and actuators give or accept voltage signals, and my controller inputs or outputs those accordingly. For example, the 4 speed has some pressure sensors to monitor the valve body behaviour, and I send some HI or LO voltage signals in emulation of it.
2. I do use FreeRTOS for the 407. I don't need to, since I use a super loop and all my memory is either static or allocated on the stack.
Ah okay. This simplifies the setup a lot. I had done some testing and validation of ECUs 9 years ago. So my questions were based on the understanding I had developed back then. Thank you for clarifying it. Again, awesome work :)
If my car relied heavily on CAN (like the next generation Commodore) I probably would have sold it.
I love CAN bus (for my own designs), but I don't see the effort of attempting to reverse engineer GM's format as worth it, especially since I had no prior experience with CAN.
Thank you :) I've got another D automotive project which I hope to write about soon.
I spend a tonne of time in the reference manual for the 6 speed, and things clicked for what my next steps should be. It was really about trying to familiarise myself with the problem as much as possible.
I used D for a while. It improves several things over C++, among them:
- More powerful metaprogramming capabilities.
- Better module and library system.
- Nicer syntax.
The problem IMO is it's just not enough to justify a total move from C++ -> D. The syntax of C++ can't really be fixed, but the other aspects can be improved without a new language.
Furthermore, many of the other downsides of C++ are still present:
- The complexity of the language, and then the sheer number of different ways of doing the same thing.
- Some pretty dark corners in the way stdlib/language feature were implemented that seemed hard to ever fix.
- The way behaviour is specified in the language is very tied to the underlying hardware: rather than explicitly describing behaviour in terms of an abstract machine, it works more in the way C++ is specified where we all know it operates on an abstract machine thanks to compiler optimizations, but the spec likes to pretend it doesn't...
And then there are problems that are introduced by D, such as the fact that a safe subset exists, but depends on GC, so there's a weird split where no "safe code" can be used in contexts where GC is unsuitable.
Contrast this to Rust, where:
- There is a true step-change in bringing safe code to all contexts, not just those where GC can be used.
- It's missing a lot of the complexity of C++. Rust is hard because it has concepts that are foreign to a lot of programmers, but the total number of features is low (compared to C++) so there are fewer surprising ways they can interact.
- Rust is a suitable replacement for C, not just C++, because it's not just adding more features.
D is easy to pick up, and has three really fast compilers. It feels like a very practical language.
Rust in comparison feels much less practical - glacial compile times and byzantine rules about manging memory. It may be 'safer' but that's a moot point when I find it all so unintuitive that I'm not going to be able to make anything with it anyway.
And I really question what these situations are where you can't have garbage collection in 2021. Hard real time systems, sure, but that's not what 99% of people are using rust for. Maybe people just like the challenge.
>And I really question what these situations are where you can't have garbage collection in 2021.
Game development, anything with a UI (GC pauses frustrate users), anything that needs high performance (scientific applications, data analysis), you name it. Ownership semantics have a side-benefit of automatic thread safety; something that is less important than memory safety (because many programs can work in one thread but almost no programs can work without allocation) but extremely valuable when needed.
How does that matter? You said "game development", not "writing a game engine". You said "data analysis", not "writing linalg algorithms", in which case we'd all have to bow to Fortran anyway.
Your argument also doesn't apply to GUI apps, anyway. C# and Java amount to a huge number of such apps, and they're self-hosted.
GC languages are vastly more productive that manual-memory languages, and for the vast majority of users, that is worth the performance hit.
If your suggestion is, "GC languages can be used to write anything so long as whatever parts can't be written in a GC language are written in a non GC language," then yes that's true. But it's also a tautology.
If you need to stay away from the GC because of some practical reason, you can always write C/C++/Rust. You implied that this is a frequent situation when it isn't. Your example of "anything with a UI" was quite a bad one.
Most projects are better off written in a GC language because the productivity benefits outweigh the performance costs.
There is a lot being said about productivity gains from GCed languages, but can you actually point me to any research showing these gains are real?
My anecdotal, unscientific experience shows that GC is a double-edged sword that maybe makes writing simple programs slightly faster, at the expense of a much worse maintainability once the code base gets big. And non-memory resource management in GCed languages without RAII is a really huge PITA that kills all productivity gains.
GC allowed memory safety until Rust happened, and that was a big gain, but now that point is moot.
In practice it is even not true, because there is a non-zero cost of interfacing between managed runtime and native non-managed code. Therefore not every piece of code that would theoretically benefit from writing in a non-managed language, could be actually rewritten.
Unreal is written in C++ but, like Unity, can be scripted in other languages. Like unity it fits the "GC language for high level scripting of non-gc code" pattern. There is certainly no debate about the feasibility of implementing game logic in Lua. Reference counting in graphics drivers is not comparable to GC in Java or C# because its lack of generality permits the use of faster algorithms that don't GC pause. Swift is a workable systems language with reference counting built in, but you should bear in mind that it doesn't have "a garbage collector" per se, like you would imagine when you hear that a language is GC'd.
I am learning Rust and SPARK2014, and I would think SPARK2014/Ada would be a better fit for high-integrity software for verifiable, embedded software than Rust. This was the older article that stimulated me to look at Ada and then SPARK2014 again:
extern crate prusti_contracts;
use prusti_contracts::*;
#[requires(something)]
#[ensures(result >= a && result >= b)]
#[ensures(result == a || result == b)]
fn max(a: i32, b: i32) -> i32 {
if a > b {
a
} else {
b
}
}
Ada seems like a fantastic language though, and the 202x edition brought some niceties to the language.
I am an Ada/SPARK novice, but on first look Prusti seems to deal with contracts, but I am not sure how much more of the Ada/SPARK system it may covergg. I used to dislike Ada and SPARK due to their verbosity, but after studying some of the embedded work in them, and what they bring to the table, I am no longer put off by that or syntax. I've seen Julia and even Elixir projects in areas that would better suit Ada/SPARK, but I think it is due to their popularity rather than applicability. But things like Elixir's Nerves platform is very interesting in bringing the BEAM to the embedded world, and I love Pluto notebooks for Julia, but for high-integrity software I think I'll try and leverage Ada/SPARK's capabilities and pedigree for now. I will look further into Prusti this weekend.
Rust's type system still lacks the expressivity of Ada. Rust has a lot to teach Ada (and you see this coming out from AdaCore's blog recently with efforts to add lifetime analysis to SPARK), but Rust has a ton to learn from Ada as well.
I agree, but I just turned 57 (been programming since 1978 for fun), and there is so much already done in Ada that powers SPARK that it will be a while for it to be tried and true. Although, with all the work on theorem provers and such, maybe it will be exponential and I'll be around to see it. I really like Zig too, but I am staying with Rust because of its inertia. At heart, I love J/APL, but I use them for wholly different reasons.
> When you enter SafeD, you leave your pointers, unchecked casts and unions at the door. Memory management is provided to you courtesy of Garbage Collection.
Does D provide the necessary tooling to be able to expose a safe API for something which needs to allocate memory, without needing a GC?
The idea that Rust is suitable to replace C and D isn't is odd to me. It's really not hard to do + we (unlike some languages, not sure about rust) actually test on embedded targets via GCC.
What I meant by this is: if you are starting a project today, and have to choose between C and C++, there are certain reasons why you might choose C over C++.
Those same reasons would apply for choosing C over D. They might not apply for choosing C over Rust.
I can't think of a reason that would apply here. For me at least if I were on a toolchain so crap I had to use C you'd have to pay me a lot of money not to work on something else.
All my embedded design work has been in C as i don't need all the extra cruft.
Also anything i want to be very fast on limited hardware i also use C and C only.
As for any hobby programming i do on the side, C is usually my goto choice, unless i want to be very esoteric.. following along the lines of:
"The enemy of art is the absence of limitations."
I find that C actually gets in my way compared to D when I am writing code with limited resources. The end result is semantically the same but with D I can avoid macros, inline asm is easier etc.
while this makes all the sense in the world to even a seasoned C programmer...
I've been doing it so long I could write macros in my sleep, and inline asm is a fun little exercise.
Though i absolutely agree, especially with someone newer, that could be a major road block. Might want to learn D just to be more efficient (even though I will never abandon my first love completely)
To give some perspective: mrustc is written mostly by one person, in C++ and it caught up to 1.39.0 recently - meaning it can "compile" rustc itself (without any type safety validation) as opposed to arbitrary Rust code.
Also C++ compilers are hard too. And optimizing C compilers are hard too...
That is very true but absolutely fine because then some fine set of engineers can do the hard lifting parts and rest of the ecosystem can thrive on stable base that core establishes. That is how things work in most of industries, not everybody is writing a compiler (or even suitable for writing one!), but the complexity compilers remove lets you build more complex pieces of engineering.
Do you need to build an entire compiler or "just" the backend/code generation to port something? Although "just" a code generation for Rust means building one for LLVM, which I'm sure is harder than some C compilers out there.
The things that make D special - culturally even - are quite niche so while it's been extremely profitable for many who do use D, D is sometimes not an easy sell in the sense that the things that D makes easy are not things you encounter in the first few minutes of using a language.
Also: Marketing, a lot decisions are made based on nothing, we're too modest (to be blunt).
As far as I know D's original design strategy, was to be a simpler to use C++ with a GC, but with the same expressive power
Over time, this proved to be a bad strategy, C++ key strength became RAII (deterministic memory management), so the GC became a failed strategy
The maintainers tried to move in different directions, adding manually memory management, making the GC optional, moved D to be a C replacement, with the -betterc compiling option, and many other tweaks and features added overtime, but nothing really caught on
This isn't a very good summary of how the language evolved.
D has basically always had the ability to not use the GC, it's only recently that we've taken an interest in replacing C. The GC has been written in D for a very long time, that wouldn't be the case if the language didn't allow manual memory from day 1.
BetterC is a nice-to-have rather than a language dialect.
Having a GC is an absolute godsend for getting clean code out of the door quickly.
on the point of the GC being a good thing to have, this is true, but not when your main objective is to replace C++, C++ key advantage being RAII deterministic manual memory management
You cant replace C++ with GC language, even 10 years ago this should have been evident to a seasoned developers such as Walter Bright and Andrei Alexandrescu
Sometimes great developers are bad product managers
Anyway, with Rust and Go, D have no where to go, I don't think it should be fixed to appeal to a wider user base, the only good strategic move they can do today, it make it better for the current user base, they have few big users, they should focus on them and the language will fade once those users move on to something else
Then don't use the GC? Ignoring that a lot of C++ developers are practically incompetent and completely unable to separate their ideology from the actual requirements of their software (I note that not one single even anecdote has been mentioned regarding the GC in this thread), D gives you the tools to do that already. I work argue not as polished as C++, but that really doesn't matter if you set out to write a new project.
Also, if you think existing D users are going to replace D with Go I don't know what to say to you. Go and Rust are literally punchlines without a need for a joke in discussions I've had with many senior people at these companies (Mostly Go). The reasons why people use D are so utterly detached from everything that has been discussed in this thread that I don't know what to say to you. Go is a bad programming language, pure and simple, good ecosystem, awful language.
"Lockheed Martin reviewed various options for the Aegis Open Architecture including the programming language and execution environment for the system. In their experiments, they found that HotSpot Java code ran comparable to C++ on an experimental 250 millisecond periodic workload. At the same time, they found that the Java language provided superior abstraction and encapsulation than C++, and they judged that retraining their existing staff of CMS-2 programmers to become effective in Java would have lower risks than attempting to train them in C++."
HotSpot was not the mainstream JVM
I see now its been opensourced, and apparently, np longer in active development, and I dont know how much of it made it into mainstream Java
Java is one of the top 3-5 most popular languages, and have huge backing
So its understandable that people found a way to make it fast, and honeslty, i dont really know how much effort does this require, but it seems from your example, it less than what C++ need
This all in all, seem counter intuitive, if Java is really as fast as C++, why is it that mainstream knowledge suggest otherwise
Either, your example is hiding something, or there is other reasons people still use C++ when they need high performance
D was meant to replace C++ not be a fast Java like language, I would argue, it achieved neither
D wanted to be a mainstream language, this is why the adopted the C/C++/Java style of programming, and again they didnt achieve this objective
D is not instinct, it still have a small dedicate user base, I just wholeheartedly think, today, you have far better options: Rust, Go, OCaml , C# , Kotlin
My example is not hiding anything beyond the fact that most people are clueless about how big Java ecosystem actually is.
Not everyone is doing Websites or Android apps.
PTC isn't using Hotspot, rather their own JVM implementation.
Just like C++, Java enjoys multiple implementations.
Just like C++, the best ones for embedded deployment with soft real time capabilities, are commercial, directly supported by hardware vendors.
D's biggest failure so far is not having a Google or Apple behind it, that would push the language no matter what naysayers have to say against the language.
Just like on iOS and Android, wanna play? Here are the allowed list of toys.
D had Andrei Alexandrescu behind it for years, he worked at facebook for a while and tried to push D there, and they did used D for while
Andrei is a big deal i would say
Since then FB moved on the build their own Ocaml based language reasonml
Julia doesn't have a big company behind, yet the language is steadily climbing the popularity ladder (and i doubt they have anyone at the calibre of Andrei Alexandrescu, but again, good pogrammer is not a good program manager)
D is not popular, because its leader failed at making it popular, they failed to give the qualities that would make it popular
A product failed, blame the product owner (designer, maker, etc..)
Why are you refusing to blame the product owner
D is not a good language, it really is not, it doesn't offer any compelling advantage to justify accepting its flaw
Or simply put, its a bad product
A bad product doesnt have to be trash, just enough bad design issue to make it bad
I would strongly recommend new developers not to touch it
there are far better option
Say it as it is, its simple, its the truth
Its functional, people use it, but its bad
C++ is also bad, but its so overwhelmingly popular that you might want to learn it
D is bad, and is unpopular
>D was meant to replace C++ not be a fast Java like language, I would argue, it achieved neither.
Cannot comprehend your logic here, one of the Java objectives was also to replace C++. It kind of achieved the objective by consistently being top 3 languages since its introduction and it achieved that by not even natively compiled, unlike D. Based on Java story, it seems that having no GC is not a required condition for success. I'd had imagined if Java is not being invented the entire Android eco-system (the world's most popular operating system) will be written in C++.
>D wanted to be a mainstream language, this is why the adopted the C/C++/Java style of programming, and again they didnt achieve this objective
Not sure what is your point here since almost every programming languages wanted to be a mainstream language including Ruby, regardless whether the author admit it or not.
>D is not instinct, it still have a small dedicate user base, I just wholeheartedly think, today, you have far better options: Rust, Go, OCaml , C# , Kotlin
I think you meant 'extinct'. Time will eventually tell and no need to be so negative. When Python was 20 years old (about the same age as D today), it literally was playing a 2nd or 3rd fiddle to PHP, TCL, Perl, R, Ruby and Matlab in their respective domains, and look where is Python now? I believe even Guido did not have predicted the astronomical rise of Python at the time.
Would it be fair to say that for some time (I wouldn't know exactly when it started) D has evolved to serve the needs of the D community rather than to attract new people?
Attracting new people is basically never (with exception of the C stuff) been the driving force behind efforts influencing D's design.
Another anecdote - Someone who hires people in D has told me definitely that D being small means that hiring for them is usually just seeing some code, i.e. there hasn't been an eternal September let's say. They can onboard people who don't know the language, but knowing D is a very good cultural (programming is easy!) filter.
Lots of stuff exist specifically to help with onboarding people into the community. Like the recent announcement of adding a C parser into the frontend.
Certainly not the sole reason, but the mix of language features puts it into a weird spot:
You have great control over memory layout and can easily embed assembler, which would be perfect for performance sensitive software like games. Yet "default" D comes with a garbage collector and - more importantly - language features that require said GC.
If you want to go the noGC route, you have to refrain from using certain language constructs, which puts you in a similar spot as with C++...
And if you actually want a GC, you might find the simple linear allocator of D to be lacking...
D is a very cool language, but it is also a lot like QTified C++... Which, well, already exists...
1. concatenating strings using the ~ operator. You can concatenate strings using malloc if you prefer.
2. closures that escape the context of the function they enclose. Instead, write a struct with fields representing the values, and make the lambda a member function of that struct. Allocate the struct instance any way you wish.
The GC is a convenient feature with lots of nice uses. Programming in D is not impaired by not using it.
Maybe something changed, but I thought array concatenation with ~, associative and dynamic arrays as well as exceptions rely on the GC as well.
It's a short list, for sure, but thats not the point:
Anyone looking into using D without GC will see that there are some language features that require special care.
At that point it becomes a valid question why one should learn about the pitfalls of GC free D, when one already knows that about the currently used language.
GC free D is low friction, but seemingly not low enough for uptake from interested parties.
> array concatenation with ~, associative and dynamic arrays as well
Yes. Walter was referring to the operator itself. Strings are arrays.
> as well as exceptions
It's not exceptions themselves, but the `new` operator. It directly allocates from the GC. That said, there is a plan to enable @nogc exceptions.
> At that point it becomes a valid question why one should learn about the pitfalls of GC free D, when one already knows that about the currently used language.
People who already know another language and are happy with it have no reason to switch. Why would they? It's people who aren't completely satisfied with a given language that are going to be more open to looking at others. And so of course then it's a matter of weighing pros and cons. Do I like the syntax? Does it feel intuitive? Am I comfortable using it? Do I find the pain points blockers or minor annoyances?
There is nothing special about D in this regard. If you aren't looking for a new language, you aren't going to try it. And if you are, you either like it or you don't.
WekaIO wrote the world's fastest filesystem in D. They did it without the GC, and went so far as to write their own GC_free standard library (which they open sourced). Their CEO talked about why in this interview:
That said "GC-free D" is not a major selling point of the language. You will not find the maintainers recommending anyone start a D project fully GC-free unless there is a very specific use case, like that of WekaIO or the blog post author. The allocation patterns in D are different than they are in Java or C#, it's clearly defined when a collection may trigger, the @nogc attribute provides compiler enforcement for avoiding GC allocations in specific functions, a command-line switch can warn you about the same if you find @nogc too much to think about (because employing @nogc does require more consideration of your architecture), and other switches can help minimize the impact of GC.
So the tools are there for anyone who needs them. There are definitely rough edges and we are forever in need of improvement, but everything is usable and people are using D in production right now.
I'm surprised you mentioned memory allocation without spotting the memory allocators in the standard library. Andrei designed the library and as far as I can tell no other language comes close when it comes to composable allocators.
I dunno why you assume that I don't know about them...
Apart from that, they came pretty late, are still in experimental, and don't change the fact that only a subset of D is usable without GC.
I very much like D, I really do, but I never encountered a usecase where the pros of using D outweight the cons.
It sits in a very very weird spot design-wise, and while Walter and Andrei tried their best to get rid of the most common problems, not much of that effort resulted in actual useful change: Still no other GC than the default linear one, the stdlib is still not fully noGC usable (and probably never will), and "proper" compile time functions are still not done, after quite a few years now...
Which is a shame, D is very close to being the perfect C++ replacement.
Ultimately, for any language to become popular, it must bring something radically new on the table (e.g. Java: relative performance, simplicity and safety; Python: immediacy; etc.), and/or have a big company behind. D doesn't have any of the two (unfortunately! I do appreciate the language).
This viewpoint is typically represented by the question "what can I do in X that I can't in C++?".
Something I personally find interesting is the thought experiment: if Golang was written by a small actor, and D by a big one, which one would have succeeded?
I don't know that it's essential that a big company be behind a language. What's essential is that the tooling and the libraries be top-notch. That's beyond the reach of an individual, or even a small team. But a large company can easily provide the resources to do that.
(The third essential is that a language do something significantly better or easier than existing languages. A language can't just be "does the same as C, but with a bit different syntax", unless it's radically better syntax. Switching languages has a cost; your new language has to pay back that investment or it won't get used.)
I can't remember where I heard this, but there's a principle that a competing product can't just be 10% better. To justify the cost of switching, it has to be 10X better.
That's kind of an uncharitable way to say, "Rust has a welcoming and beginner-friendly community". It's not like there's a marketing team buying Facebook ads.
I think that's your vision of marketing. Marketing by word of mouth because you really like a product is still marketing, and the Rust community is really good at that.
The Rust community realized early that if they wanted to succeed, they had to talk about Rust a lot, show good examples, be beginner friendly to avoid people picking it up and dropping it quikly. But that "marketing" is also things like a really good package manager, really good compiler errors, a really good VSCode extensions. Many communities don't have this (especially the new ones) and this makes developing in Rust more of a joy than in let's say OCaml or even JS.
Not different enough to be worth switching from Java/C++ with their much bigger and more established communities. This was especially true earlier in it's history when it required GC. Now it doesn't, but it has to compete with Rust which can also offer memory safety.
Funkwerk, one of the first companies to adopt D back in 2008, switched their passenger information system from Java and C++ to D. They weren't just on the look out for something different. They had a real problem to solve, tried out a few languages, and settled on D. They're still using it today (they moved from D1 to D2). And if you're riding certain rail networks in Europe, you're benefiting from it.
> Not different enough to be worth switching from Java/C++ with their much bigger and more established communities.
Companies using Java or C++ don't switch because a language is "sufficiently different". I've been involved in programming language discussions for decades and I've never heard of a company switching to a language because it was different from what they were already using, though being too different is a common reason for not switching.
{For those not aware, D has intentionally kept compatibility with C as a priority, to the point that you can set a compiler flag and restrict yourself to "betterC". You can translate C code to D without making many changes to it.}
"Different" is not a reason to switch, but "not different enough" is a reason not to switch.
When switching is costly, the potential upside must be big. When the other language seems similar, the upside also seems limited. When there are few differences, you can rationalize staying with the old language, because it may catch up with the features, or you can emulate the missing features, or just live without them, if the differences are small.
This is getting into a fuzzy area where one person's big difference is another person's small difference. I'd consider D templates to be a small difference from C++ templates in terms of the language[1] but big enough in terms of productivity that it would make sense to start a new project in D over C++ for that reason alone.
[1] A random commenter on HN might well conclude that there's no benefit to D's templates without using them.
So far, it's shaping up nicely. I am indeed kicking myself for not doing it a while ago, but I'm a better programmer now than then, and it's going to be a better job.
But Go came and succeeded. Would you attritube this to Google's marketing, products like Docker/Kubernetes, or the simplicity of the language? Maybe something else?
A lot of people have mentioned a lot of reasons, marketing, corporate support, etc...
I think a language technology needs at least one, but ideally a few, flag ship projects using it. It provides some examples for people to see, it shows the "why" and then it also connotes that it's living and good. I don't think it has to be big, just good. Ripgrep is a prime example, there are a few other smaller tools in Rust that are nice, well put together tools that do a nicer or better job than the old standards.
You can talk about why something is nice or better, but actually showing people that it is probably convinces more.
I feel like a large reason for that is that D is a properly boring language and I mean that in the best way possible. I have yet to be unpleasantly surprised by D in the way other languages seem to be specifically designed towards.
While this makes D a deeply pleasant language to use, it also makes it tough to sell. It doesn't have any whizz bang features you can get across in an elevator pitch.
Plenty of great answers above already. What I also think is a valid argument is that in order to appreciate the language, one has to be a seasoned developer hence many heated discussions on HN or Reddit. It reminds me of Lua, where at least one person would mention something about 1-index arrays and nil element behaviour.
I think there are just two big factors - garbage collection and tools. When it was made garbage collection seemed reasonable, but with modern C++ and rust we now know that tracking ownership through different scopes solves the same problems very well with none of the downsides of garbage collection. If you look at D, Julia, C#, Java, Ocaml, etc. etc. over and over you see people eventually fighting with the garbage collection over throughput and latency.
D to my knowledge has never fully transitioned to garbage collection being a thing of the past.
For tools I think D fell into a common trap, which is to just keep working on the language itself. Eventually the lack of debugger, real time syntax checking and auto completion take their toll and something like C++ seems better even with the rough edges of the language itself.
Challenging to overcome languages like C++, Rust, Java, and C#. D seems to sit somewhere in between, a better C++, but with (optional) GC. The thing is, Java and C# are already making strides into that space.
I am curious to see where Java are C# are making progress towards optional GC.
This specific article talks about using No GC aka "betterC".
D has GC by default; the use of GC is convenient and mainstream as most popular languages show - Java/C#/Python etc. What D gives is the unique ability to do No GC programming for the cases where GC is not desirable. Very few languages offer this capability.
Zig is interesting in this arena, but it approaches the problem from the other angle. It is manual memory management by default, but you can explicitly choose which memory management technique you want to use - at compile time.
C# has added a lot of control over memory layout. Span [0], structs etc. I am hoping they add more D like features (@nogc) to the language. Java itself has just made strides on reducing GC pause times [1].
Granted, this isn't optional GC, but does D really give you that? Don't you lose the entire ecosystem and stdlib with -asBetterC? Why would I choose that over rust/zig/c++?
> Granted, this isn't optional GC, but does D really give you that? Don't you lose the entire ecosystem and stdlib with -asBetterC?
-betterC is not the only way to avoid the GC in D, just the most extreme. The original motivation for -betterC was to ease porting C code to D. Walter has used it for that to port a good bit of his old C code over. But it's also suited for the space in which the blog author is using it, and some people just prefer it. You always have access to the existing C ecosystem, but there are people writing -betterC libraries in the D ecosystem. And as more people use it, I expect that space will grow.
If one sets the requirement of having manual memory management in a mixed language, then:
1. either they don't use any library, including the standard one,
2. or the (standard) libraries must be written in both manual and managed memory management versions.
Additionally, the language must include extra syntax for memory allocation and access. This doesn't event include safety-related semantics, like Rust, which would be very hard to bolt-in (language-wise).
I hardly see any advantage in Java/C# having this functionality; Oracle is actually putting lots of effort into improving their garbage collectors. Java does actually have manual memory management (through Unsafe), although it's rudimentary; for the reason mentioned, I doubt it will ever be improved/expanded.
Back when D originally debuted, I couldn't separate it in my mind from C# and Java, despite the fact that you could manage your own memory. It felt like it fit into the same space, yet didn't have a compelling ecosystem. (Competing standard libraries did not help their case!)
Java and C# also offered similar capabilities when D appeared.
Granted on Java side it required sun.misc.Unsafe, JNI or Real-Time JSR, while on C# side, a mix of structs, SafeHandle, MarshalInterop, unsafe and eventually C++/CLI.
So while not as pleasant as D, the cost to drop those eco-systems wasn't worth the cost to switch, and now 10 years later those eco-systems have doubled down on improving the experience for low level coding.
This makes it quite hard to sell D to those potential users.
> This has made my code significantly clearer. My code can accurately follow the flow of data without polluting my stack with single-use variables, nesting many function calls, or other sorts of clutter.
This is also pretty common practice in Haskell. Though Haskeller's typically have a higher tolerance for reading their code backwards. (But you don't need to. It's easy to define operators that arrange your code in the other direction.)
Products in https://www.auburnsounds.com/
also PDF generation, SIMD, static websites (CommonMark), and a lot of internal tools. There is a wide gamut of applicability. (EDIT: I have become that blurb programmer :o )
The units are a mix of D's UFCS and metaprogramming. I find it helps keep track of which units are used where in the code base, and stops me from accidently running operations on wrong unit types and such.
Injector width / time pretty much means the same thing (at least in my code base). My apologies for the confusion.
Meh... after not more than my first month into D this syntax grew on me and now I just use `1.writeln` everywhere. More than a few years later, I can't think of a single issue this has ever caused me.
UFCS as a concept is fantastic but the one hangup is that D's language server implementation by the community and
its IDE integration can't handle it because of the complexity.
It's possible to implement, because Nim's language server handles UFCS, but atm D's doesn't do it (it's written pretty much by one people)
So personally I avoid UFCS except for very simple/common function like "to!" because it breaks the intellisense for that call.
Though if I knew the language inside and out probably I wouldn't care.
It's still my "favorite" language.
-----
SIDE NOTE: This single person wrote the D lang server, and has maintained it, written and maintained the VS Code extension, and other fundamental tooling + libs for years.
If you use D and feel like sponsoring someone, consider sponsoring them, or Rainers (VisualD), or the maintainers or LDC or GDC, also single individuals for the most part.
The language server doesn't do it because it's only a parser whereas making UFCS work properly would presumably require a full semantic analyser. By no means impossible to do, just no one has taken the plunge yet.
And since this is about dlang a bit...
My favorite part of D compared to cpp, was metaprogramming syntax. (i.e. NOT '<' and '>')
I was so sad when I got to know that the only thing that rust took from cpp, was '<' and '>'.
It's really beyond me why would Rust designers adopted the '<' and '>' symbols. If I'm not mistaken Walter had specifically mentioned that he's avoided these symbols based on his experience on implementing C++ compiler in the early days of C++. Due to the ambiguity of the symbols with other operations' symbol, their inclusion will require extra symbol look up table and this will significantly increased parsing and hence overall compilation time. Based on the complaints on Rust compilation time that you see in HN, probably he's right after all.
One of the design principles of D is to create compiler friendly programming language and this is evident with the higher speed compilation of the D programs in comparison to similar program in C++ and Rust. Comparatively speaking, Go also has a very fast compilation time but Go currently does not support generic yet, and there's that.
In addition, another design principle of D is to be as intuitive as possible and programmer friendly compiled programming language. If you think this should be easy please check this video regarding of this Professor to try to completely compile R to no avail in 10 years during a keynote speech in a recent major R conference [1]. For examples, this is the reason that you have UFCS in D and there's also no macro in D. You can see that some of later programming languages agreeing with D approaches and copying this UFCS feature. On the overall language idioms, D want to be easily program similar to Python but compiled, i.e. fast in compilation and running time. FYI, there is even a book specifically written for Python programmers if they want try and perhaps migrate to D [2].
I agree, the syntax is much clearer than C++. The very first prototype was in C++, but I found myself frequently frustrated with the language. I find D's features make me more productive.
> From the factory, it came with a rubbish four-speed automatic gearbox. During 18 months of ownership, I destroyed four gearboxes.
[I'm from Europe.] I absolutely don't get this. Just... what? Four gearboxes? I don't know anyone who destroyed a single one - even after an entire lifetime of daily driving, but I don't mean Mercedeses - more like Škodas. What's up with American cars? Is this common?
Keep in mind, with the 4 speeds I drove casually. With this 6 speed, I can push it hard and it's still going strong almost a year later.
They're quite an old (American) design bolted to a modern engine. It simply doesn't mix well. 4 speeds (4L60e) are the bread and butter of automatic transmission rebuilders in Australia.
My father killed one in his daily driver, and all it did was go 20km each way to and from work. My Aunt's Commodore was recently in the shop getting a new 4L60e. They're simply not suited to the car.
They're owned by GM now. Modern ones will be GM parts-bin cars. Going through that many GM transmissions is possible. This is why GM cars have horrible resale value and anything over 150k miles is on borrowed time.
Holden has been owned by GM since the 1930s and has been building its own vehicles since 1948. Holden ceased building cars in 2017 and was disbanded in 2020 (RIP).
I like D and could pick it up easily. It feels a lot like C without memory management overhead, Ada-inspired safety and lots of productivity feats. However, where D really shines is the amount of time between learning the language and starting doing something useful in it.
It is. I contacted a VicRoads approved engineer in regards to this project, and I received the all clear. I've been pulled over by cops, and they were cool with it.
My insurance is ok with it, too.
It does have a software watchdog, and failing that, the gearbox's hydraulics have a safety mechanism that allows for some limited driving.
Almost certainly. Basically all "under the hood" mods like this are— street legality for a vehicle you build or modify yourself is a surprisingly narrow band of requirements that are mostly around safety equipment like lights, horn, etc:
I have to go to bed, I have work in about 4 hours, so I'll reply when I can.