5 ms·
As far as I know, D does not have ADTs (algebraic data types, a.k.a. tagged unions, a.k.a. Rust enums). I see that it has "enums" and "unions", but neither of t
by justinpombrio 6y ago
As far as I know, D does not have ADTs (algebraic data types, a.k.a. tagged unions, a.k.a. Rust enums). I see that it has "enums" and "unions", but neither of these appear to be ADTs if I'm reading them correctly.
And Rust's borrow checker can give very strong guarantees that aren't present in any other mainstream language that I'm aware of. In Rust, you can pass mutable references to large data structures between threads, without copying or GC or any type of runtime checking (e.g. Mutexes), and the borrow checker will guarantee that you can't have a data race (data race = concurrent read & write). In comparison, I believe that in Haskell you'd do this with GC, in Java you'd do it with GC and a mutex, and in C you'd do it very carefully.
As another example, in Java if you modify an ArrayList while iterating over it, you'll get a ConcurrentModificationException. In Rust, you can't. The borrow checker won't let your program compile.
The cost of this borrow checker is huge: every reference in every program needs to be annotation with whether it's shared or mutable, and you often need to splatter confusing lifetime annotations all over the place. It adds a big learning curve to the language.
I don't know the details of D's ownership system, but it's not like Rust's borrow checker. Does someone who does know more want to describe it? I've just seen the language reference page here, that describes "scope" and "returns".
https://dlang.org/spec/memory-safe-d.html https://dlang.org/spec/memory-safe-d.html
- mhh__ 6y agoD's borrow checker is only semi-documented/WIP at the moment. https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in-d/ https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in... Basically D just needs that big break to actually get things done. There are some absolutely brilliant people working on D but there's only so much sweat people will donate (some people are paid but I imagine rust probably has upwards of a hundred full time staff given that Mozilla and Microsoft use it in an official capacity)
- crazypython 6y agoD does have smart people working on it, but like you said, maybe not enough. Walter Bright, creator of D, single-handedly created the first C++ compiler that compiled directly to machine code. Andrei Alexandrescu was on the C++ committee.
- vmchale 6y agoAlso D has a gcc backend. Which is nice but it's still missing some of Rust's features.
- welkam 6y agoIts more than that. D is part of GCC - The GNU Compiler Collection. Meaning that if you use linux and have recent GCC you already have D compiler.
- datman347 6y agoDon't know anyone that uses the D GCC compiler, it is still playing catch up. The frequency of new D releases with intended and unintended breaking changes, usually source only ever compiles for a very narrow range of versions of D. What people usually focus on is the latest, unless there is a new bug that prevents them from using the newest version.
- datman347 6y agoYes it is very much still a WIP, what is currently implemented, how it is implemented and the fact it is already in the compiler (without a switch) is rather disappointing. Unless the implementation drastically changes, the outlook for the feature is not good at all.
- jjpe 6y ago> The cost of this borrow checker is huge: every reference in every program needs to be annotation with whether it's shared or mutable No. You need to "annotate" a mutable binding since bindings are immutable by default. But that also means that immutable bindings (ie the vast majority) does not to be "annotated". And even when you do need to, you literally just add the keyword `mut` as in `let mut foo = 42;`. > and you often need to splatter confusing lifetime annotations all over the place. It adds a big learning curve to the language. Again an extreme exaggeration. There are a few cases here and there where you need lifetime annotations, but most often the compiler simply infers them for you, allowing you to elide them completely. Specifically, you only need to do it yourself when it's ambiguous from which input(s) the output is derived.
- justinpombrio 6y agoTotally agree. I should have said "add sufficient annotations to distinguish shared references from mutable references", and "occassionally need to splatter confusing lifetime annotations all over the place". EDIT: What's really relevant is that you can look at a Rust type, and tell whether it's shared, mutable, or owned; this is what Rust's borrow checker derives its power from. Likewise, Haskell's type system derives its (equally amazing) powers from the fact that you can look at a Haskell function's type signature, and tell what kinds of side effects it has. (Sometimes people think that Haskell functions don't have side effects in the sense that they never mutate anything. This is wrong; Haskell has mutable arrays in its standard library. Rather, it's that all side effects are reflected in a function's type signature.) https://hackage.haskell.org/package/array-0.5.4.0/docs/Data-Array-MArray.html#g:4 https://hackage.haskell.org/package/array-0.5.4.0/docs/Data-... I write Rust code for work, and we have a large codebase. We manage it pretty well, but there are definitely still innocuous looking changes that require adding lifetime annotations all over the place to avoid confusing error messages. Rust is my favorite language by far (I get the impression you like it too and are defending it). I think the costs of its borrow checker are worth it, but they are significant costs.
- he_the_great 6y agoD implementation of algebraic type is in the library. https://dlang.org/phobos/std_variant.html#.Algebraic https://dlang.org/phobos/std_variant.html#.Algebraic I have not utilized tagged unions outside this type so I'm not one to comment on any deficiency.