5 ms·
IMHO D just missed the mark with the GC in core. It was released in a time where a replacement for C++ was sorely needed, and it tried to position itself as tha
by rafaelmn 8mo ago
IMHO D just missed the mark with the GC in core. It was released in a time where a replacement for C++ was sorely needed, and it tried to position itself as that (obvious from the name).
But by including the GC/runtime it went into a category with C# and Java which are much better options if you're fine with shipping a runtime and GC. Eventually Go showed up to crowd out this space even further.
Meanwhile in the C/C++ replacement camp there was nothing credible until Rust showed up, and nowadays I think Zig is what D wanted to be with more momentum behind it.
Still kind of salty about the directions they took because we could have had a viable C++ alternative way earlier - I remember getting excited about the language a lifetime ago :D
- fuhsnn 8mo agoFIl-C, the new memory-safe C/C++ compiler actually achieved that through introducing a GC, with that in mind I'd say D was kind of a misunderstood prodigy in retrospect.
- rafaelmn 8mo agoThere's two classes of programs - stuff written in C for historic reasons that could have been written in higher level language but rewrite is too expensive - fill c. Stuff where you need low level - Rust/C++/Zig
- brabel 8mo agoFillC works fine with all C code no matter how low level. There’s a small performance overhead but for almost every scenario it’s an acceptable overhead!
- jibal 8mo agoup to 5x is not what most people mean by small.
- arcadia_leak 8mo agoDepends on what the multiplicand is.
- jibal 8mo agoNot really.
- brabel 8mo agoFor most apps it’s much less than that and in most cases it’s unnoticeable. I think it would be more productive if you could point out an app that has noticeably worse performance on FillC, so that the cause for that could be looked at and perhaps even fixed, so that eventually there would be neatly zero examples like that.
- jibal 8mo agoThe fact that inserting runtime checks and doing garbage collecting slows things down is not a bug, not something that needs to be fixed. As for "I think it would be move productive if you ...", that's just rude. I wasn't criticizing Fil-C, just pointing out an inaccuracy.
- brabel 8mo agoYou did not point out any inaccuracy, you literally made baseless comment about it being "up to 5 times" slower without providing an example where that's the case. "That's just rude" - oh my, never though asking for evidence of a performance problem on HN would be "rude". And yes, if something is actually 5x slower, it's very likely a performance bug that can be fixed, as FillC's author has made it clear in several opportunities.
- jibal 8mo ago> you literally made baseless comment It's sad that people lie here. It's commonly recognized that programs run 1.5-5 times slower. > if something is actually 5x slower, it's very likely a performance bug that can be fixed, as FillC's author has made it clear in several opportunities. Another lie from someone who doesn't even know what the program is called.
- uecker 8mo agoNa, there are only three classes: stuff where you need simplicity, fast compilation times, portability, interoperability with legacy systems, or high-performance - C. Stuff where you need perfect memory safety: Fil-C. And stuff where you need a combination: C + formal verification. Not sure where I would Rust/C++/Zig (none of those offers perfect memory safety in practice)
- arcadia_leak 8mo agoI'd rather say that the GC is the superpower of the language. It allows you to quickly prototype without focusing too much on performance, but it also allows you to come back to the exact same piece of code and rewrite it using malloc at any time. C# or Java don't have this, nor can they compile C code and seamlessly interoperate with it — but in D, this is effortless. Furthermore, if you dig deeper, you'll find that D offers far greater control over its garbage collector than any other high-level language, to the point that you can eagerly free chunks of allocated memory, minimizing or eliminating garbage collector stops where it matters.
- rafaelmn 8mo ago> C# or Java don't have this, nor can they compile C code and seamlessly interoperate with it — but in D, this is effortless. C# C interop is pretty smooth, Java is a different story. The fact that C# is becoming the GC language in game dev is proving my point. >Furthermore, if you dig deeper, you'll find that D offers far greater control over its garbage collector than any other high-level language, to the point that you can eagerly free chunks of allocated memory, minimizing or eliminating garbage collector stops where it matters. Yes, and the no-gc stuff was just attempts to backpedal on the wrong initial decision to fit into the use-cases they should have targeted from the start in my opinion. Look D was an OK language but it had no corporate backing and there was no case where it was "the only good solution". If it was an actual C++ modernization attempt that stayed C compatible it would have seen much better adoption.
- arcadia_leak 8mo ago> C# C interop is pretty smooth True, but you still need to either generate or manually write the bindings. In D, you just import the C headers directly without depending on the bindings' maintainers. > If it was an actual C++ modernization attempt that stayed C compatible it would have seen much better Any D compiler is literally also a C compiler. I sincerely don't know how can one be more C compatible than that. > Yes, and the no-gc stuff was just attempts to backpedal on the wrong initial decision I think that it was more of an attempt to appease folks who won't use GC even with a gun to their head.
- optionalsquid 8mo agoMy (likely unfair) impression of D is that it feels a bit rudderless: It is trying to be too many things to too many people, and as a consequence it doesn't really stand out compared to the languages that commit to a paradigm. Do you want GC? Great! Do not want GC? Well, you can turn it off, and lose access to most things. Do you want a borrow-checker? Great, D does that as well, though less wholeheartedly than Rust. Do you want a safer C/memory safety? There's the SafeD mode. And probably more that I forget. I wonder if all these different (often incompatible) ways of using D ends up fragmenting the D ecosystem, and in turn make it that much harder for it to gain critical mass
- DeathArrow 8mo ago>My (likely unfair) impression of D is that it feels a bit rudderless: It is trying to be too many things to too many people, and as a consequence it doesn't really stand out compared to the languages that commit to a paradigm. My (likely unfair) impression of D is that it feels a bit rudderless: It is trying to be too many things to too many people, and as a consequence it doesn't really stand out compared to the languages that commit to a paradigm. Nim kind of does that, too.
- cb321 8mo agoThis can very clearly be said about C++ as well, which may have started out as C With Classes but became very kitchen sinky. Most things that get used accrete a lot of features over time, though. FWIW, I think "standing out" due to paradigm commitment is mostly downstream of "xyz-purity => fewer ways to do things => have to think/work more within the constraints given". This then begs various other important questions, of course.. E.g., do said constraints actually buy users things of value overcoming their costs, and if so for what user subpopulations? Most adoption is just hype-driven, though. Not claiming you said otherwise, but I also don't think the kind of standing out you're talking about correlates so well to marketing. E.g., browsers marketed Javascript (which few praised for its PLang properties in early versions).
- cardanome 8mo ago> My (likely unfair) impression of D is that it feels a bit rudderless The more positive phrasing would be that it is a very pragmatic language. And I really like this. Currently opinionated langues are really in vogue. Yes they are easier to market but I have personally very soured on this approach now that I am a bit older. There is not one right way to program. It is fun to use on opinionated language until you hit a problem that it doesn't cover very well and suddenly you are in a world of pain. I like languages that give me escape hatches. That allow me to program they way I want to.
- gorgonical 8mo agoRe: the point about Zig: Especially considering I used and played a lot with D's BetterC model when I was a student, I wonder as a language designer what Walter thinks about the development and rise in popularity of Zig. Of course, thinking "strategically" about a language's adoption comes off as Machiavellian in a crowd of tinkers/engineers, but I can't help but wonder.
- Dwedit 8mo agoZig got too much in to avoiding "hidden behavior" that destructors and operator overloading were banned. Operator overloading is indeed a mess, but destructors are too useful. The only compromise for destructors was adding the "defer" feature. (Was there ever a corresponding "error if you don't defer" feature?)
- jibal 8mo agoNo, defer is always optional, which makes it highly error prone. There's errdefer, which only defers if there was an error, but presumably you meant what you wrote, and not that. BTW, D was the first language to have defer, invented by Andrei Alexandrescu who urged Walter Bright to add it to D 2.0 ... in D it's spelled scope(exit) = defer, scope(failure) = errdefer, and scope(success) which is only run if no error.
- pron 8mo ago> GC/runtime 1. Runtime: A runtime is any code that is not a direct result of compiling the program's code (i.e. it is used across different programs) that is linked, either statically or dynamically, into the executable. I remember that when I learnt C in the eighties, the book said that C isn't just a language but a rich runtime. Rust also has a rich runtime. It's true that you can write Rust in a mode without a runtime, but then you can barely even use strings, and most Rust programs use the runtime. What's different about Java (in the way it's most commonly used) isn't that it has a runtime, but that it relies on a JIT compiler included in the runtime. A JIT has pros and cons, but they're not a general feature of "a runtime". 2. GC: A garbage collector is any mechanism that automatically reuses a heap object's memory after it becomes unreachable. The two classic GC designs, reference counting and tracing, date back to the sixties, and have evolved in different ways. E.g. in the eighties and nineties there were GC designs where the compiler could either infer a non-escaping object's lifetime and statically insert a `free` or have the language track lifetimes ("regions", 1994) and have the compiler statically insert a `free` based on information annotated in the language. On the other hand, in the eighties Andrew Appel famously showed that moving tracing collectors "can be faster than stack allocation". So different GCs employ different combination of static inference and dynamic information on object reachability to optimise for different things, such as footprint or throughput. There are tradeoffs between having a GC or not, and they also exist between Rust (GC) and Zig (no GC), e.g. around arenas, but most tradeoffs are among the different GC algorithms. Java, Go, and Rust use very different GCs with different tradeoffs. So the problem with using the terms "runtime" and "GC" colloquially as they're used today is not so much that it differs from the literature, but that it misses what the actual tradeoffs are. We can talk about the pros and cons of linking a runtime statically or dynamically, we can talk about the pros and cons of AOT vs. JIT compilation, and we can talk about the pros and cost of a refcounting/"static" GC algorithm vs a moving tracing algorithm, but talking in general about having a GC/runtime or not, even if these things mean something specific in the colloquial usage, is not very useful because it doesn't express the most relevant properties.
- ceteia 8mo agoDoes Rust really require reference counting? I thought Rust programs only used reference counting when types like Rc and Arc are used. Swift seems to require reference counting significantly more than Rust.
- ibgeek 8mo agoI used to think of D as the same category as C# and Java, but I realized that it has two important differences. (I am much more experienced with Java/JVM than C#/.Net, so this may not all apply.) 1. Very load overhead calling of native libraries. Wrapping native libraries from Java using JNI requires quite a bit of complex code, configuring the build system, and the overhead of the calls. So, most projects only use libraries written in a JVM-language -- the integration is not nearly as widespread as seen in the Python world. The Foreign Function and Memory (FFM) API is supposed to make this a lot easier and faster. We'll see if projects start to integrate native libraries more frequently. My understanding is that foreign function calls in Go are also expensive. 2. Doesn't require a VM. Java and C# require a VM. D (like Go) generate native binaries. As such, D is a really great choice when you need to write glue code around native libraries. D makes it easy, the calls are low overhead, and there isn't much need for data marshaling and un-marshaling because the data type representations are consistent. D has lower cognitive overhead, more guardrails (which are useful when quickly prototyping code), and a faster / more convenient compile-debug loop, especially wrt to C++ templates versus D generics.
- pjmlp 8mo ago1. Java nowadays has Panama 2. Java and C# can also generate native binaries, just like Go, no need for VM. 3. C++ nowadays has concepts, modules and compile time execution This wasn't true in 2010, but D has let them catch up with missing features.
- thezipcreator 8mo agowhat are you referring to regarding Java? I'm aware C# has AOT (and il2cpp for Unity projects) but I don't recall hearing about any sort of Java native binary that isn't just shipping a VM and java bytecode (ignoring the short-lived GNU java compiler).
- pjmlp 8mo agoJava has had AOT compilers since around 2000, they only happened to be commercial, Excelsior JET was the most famous one. There were several vendors selling AOT compilers for embedded systems, nowadays they are concentrated into two vendors, PTC and Aicas. Then you have the free beer compilers GraalVM and OpenJ9, which are basically the reason why companies like Excelsior JET ended up closing shop. Also .NET has had many flavours, starting with NGEN, Mono AOT, Bartok, MDIL, .NET Native, and nowadays Native AOT. Both ecosystems are similar to Lisp/Scheme nowadays, having a mix of JIT and AOT toolchains, each with its plus and minus, allowing the developers to pick and choose the best approach for their deployment scenario.
- ksec 8mo agoI continue to think a subset of D without GC, commonly known as "D as C" or Das C could have been marketed as a language of its own with specific target audience in direct competition with Zig. But I think Walter quite like what D is today.