
Comparison between Rust and D - dumindunuwan
https://maikklein.github.io/post/cmp-rust-d/
======
nachtigall
Says not much about garbage collection: Rust does not need one, D (at least
its stdlib) needs it. How about Nulls or concurrency?

Seems to go very much into details about syntax bike shedding but not saying
much about the more "global" design differences.

~~~
qznc
There one big issues, where I think D might make progress:

Combine GC and non-GC in a single application. This would be great for game
programming for example. Handle audio and video in a soft-real-time non-GC
thread. Handle other stuff like game logic in a GC thread, such that it is
easier to write. The hard part is that GC usually requires stop-the-world. You
can currently do this [0] in D, but it is error prone. Rust tackles this
problem from the "other side": First make it safe, then possible.

[0] [https://p0nce.github.io/d-idioms/#The-impossible-real-
time-t...](https://p0nce.github.io/d-idioms/#The-impossible-real-time-thread)

~~~
Manishearth
> Combine GC and non-GC in a single application.

Rust is actively working on this, in fact.

The idea is to eventually have a Gc<T>-like type, like Rc<T>, which can be
used on specific things. It will interact fine with the regular heap, so
`Vec<Gc<Foo>>` where `Foo` contains a `Box<Gc<T>>` will still work.

You can then selectively apply this Gc<T> to things which need it. For example
if you have a large graphy-datastructure in your code and don't want to bother
with weak pointers. Or if you are doing FFI with a language that does have GC.

Rust itself would not have the Gc<T> type in the stdlib, it would only contain
a couple of traits and compiler intrinsics that are useful for a GC. (The idea
is to be able to turn on LLVM stack maps and use it for GC rooting). So you
can write a gc for your specific use case (even if that use case is just safe
bindings to a different GC from a runtime you are interacting with!) and it
should work. In fact, in the design so far it seems like multiple GC
implementations will be able to exist in the same application, and _perhaps_
even safely interact (you can control whether you want this to be possible
using the type system; I'm not sure if there is ever a case where this would
be needed)

This would of course, still be safe. It would not be possible to violate GC
invariants using safe code, nor would it be possible for the GC to violate
regular safety invariants.

~~~
bluejekyll
My biggest concern with the Gc ideas floating around Rust right now is that
they may infect your program through dependencies.

I guess I'm mostly worried about Gc being used by a large number of libraries,
to the extent that it might not matter if stdlib implements it or not, because
by using some very popular library you'd end up pulling in this runtime
dependency.

Part of me loves the flexibility this will bring to application design, but it
could be a slippery slope.

~~~
kibwen
If such a popular GC-using dependency came into existence, then there would
surely be demand for a drop-in replacement that didn't use GC.

Remember, even the proposed Gc<T> type provides very little in the way of
ergonomics (at least compared to garbage-collected types in pervasively-GC'd
languages). Essentially it would just be a souped-up Rc<T> with no need for
weak pointers to resolve cycles. Alternatively, it would only be used to
interoperate with a foreign codebase that already uses GC, like SpiderMonkey
or V8.

Given that people tend to only be writing Rust in the first place if they put
a large degree of value on performant solutions, I'm not too worried about the
library ecosystem suddenly sneaking in GC everywhere, especially since the Rc
type is _already_ halfway to garbage collection, and I don't see it used
unduly in the wild.

------
scotty79
Another language you might consider is Nim which is more like D because it
doesn't have specific selling point like Rust. It's very flexible and
reasonable though and Python programmers will feel there immediately at home.
You have GC there but you might opt out of it and/or let it run at specific
times and for specific amount of time to manage gc pauses.

------
Const-me
This article only covers the code. For the projects I work on (mostly C++
and/or C#), about 50% of decisions I make while coding is about data, not
code.

IMO, Rust just not good enough for creating complex specialized data
structures.

Even a trivial tree is hard to implement in Rust, and the implementation will
be severely limited: [https://github.com/SimonSapin/rust-
forest](https://github.com/SimonSapin/rust-forest)

D surely has it’s problems as well (in short, I think the language itself is
very good, but its runtime and libraries still need a lot of work), but at
least it’s good for complex data structures.

~~~
steveklabnik
Yes, internals of data structures often need unsafe. At least with Cargo, and
generics, you can implement them once, and then share them amongst projects.
It's also why we have a fair number of data structures in the standard
library; they will be audited a bit more heavily this way.

~~~
Const-me
Even using unsafe, are you sure I can implement e.g. efficient linked list
data structure?

By “efficient” I mean I want to split my list in two for O(1) complexity, like
other programming languages do.

~~~
frankmcsherry
Here is a version ([https://is.gd/bFCpMq](https://is.gd/bFCpMq)) that might be
instructive. It is based on a simple ref count cycle of structs like:

    
    
        pub struct ListNode<T> {
            data: T,
            prev: Weak<RefCell<ListNode<T>>>,
            next: Rc<RefCell<ListNode<T>>>,
        }
    

The code linked above probably has bugs (for sure with singleton lists), but I
hope you get the idea. It allows you to splice lists in and out in constant
time.

Also, the code doesn't use `unsafe`. Now, you would need to use `unsafe`
somewhere to actually _create_ a list, in order to initialize the fields (or
you could change the type of `next` to be `Option<...>`). However, the use of
`unsafe` would be limited to that method. This tries to get at the difference
between (i) occasionally using `unsafe` and (ii) having no safety guarantees
at all.

There are probably lots of other pain points that you can bring up, and I'm
not trying to say this should be good enough, but I thought it might help
explain what is possible.

------
programLyrique
I'd really like to have type-level numbers natively in Rust. Implementing a
vector generic on its dimensions seems to be so much easier in D!

Any prospect about that?

~~~
bjz_
There is definitely a prospect! The core team understands the need. It still
needs an RFC though, and once that is accepted it will have to make its way
from nightly, to beta, then finally to stable. So alas, not any time soon. :(

~~~
yberreby
There's an RFC that could address the lack of type-level integers:
[https://github.com/rust-lang/rfcs/pull/1657](https://github.com/rust-
lang/rfcs/pull/1657)

~~~
bjz_
Oh duh, I forgot about that - even commented on a few days ago!

------
jpgvm
This is really neat. I have dabbled in Rust and have been meaning to go back
and look at D.

The other linked posts regarding meta-programming features of D are also
great.

------
teamhappy
I think the section about immutability should mention that this is possible in
Rust:

    
    
      fn main() {
        let x = true;
        let x = false;
      }
    

I was pretty disappointed when I found out about it.

~~~
pcwalton
I was responsible for this design decision. For me, shadowing is really useful
and I use it all the time. It's especially useful for creating new, slightly
different modifications of earlier values when you don't want to keep coming
up with new names all the time—this is common when making heavy use of
immutable variables.

Some people don't like it, and if you don't you can use clippy to disallow it.
From what I've seen, most Rust code does use shadowing.

~~~
teamhappy
> I was responsible for this design decision.

Dun dun duuun

I used to write a lot of C++ and my idea of immutability always was that if I
see a variable declaration at the top of a function and scroll down to where
it's used (without reading the code in the middle) I can assume nothing
happened to the variable.

Then I started to learn Haskell something like a year ago and found out that
shadowing is not only allowed but used by people. Especially in Haskell (or
OCaml for that matter) where you can just use x' for a slightly modified
version of x. I don't know. Maybe I get used to it one day.

------
yarrel
Rust: people use.

D: people don't.

------
d33
I'm getting the impression that D is a failure. Is there any bigger project
written in it? If not, why would it fail?

~~~
Manishearth
People use D, and it is a pretty decent language.

I'm not an avid D user, but I have a guess as to why it is not so widely used.

To me, D is somewhat of a "I like C++s features and ergonomics and want a
similar languages with all the features built in from the ground up" (+awesome
metaprogramming). One of C++s drawbacks is that features have been bolted on
in hacky ways due to backwards compatibility issues. D is like C++, but
without this. It is a good goal, and from my limited experience with D I think
they have achieved it well.

Thing is, such a language will largely be adopted by people who use C++. And
the problem with these folks is that _they already know C++_. Once you are
used to it it doesn't feel so bad. Despite its drawbacks, C++ has lots of
tooling, a large ecosystem, and familiarity.

Rust is less affected by this for two reasons. One is that it gets a lot of
production users from non-C++ shops who want to use a systems language to
speed up their Python/etc tight loops. They would rather not worry about
segfaults and stuff. The other is that for C++ users, Rust scratches a large
itch. The learning curve for Rust is a lot worse than D, but for many the
benefits might overcome this. You can't get used to segfaults the way you get
used to template metaprogramming.

I would give D time. These issues just slow adoption, not stop it. That is
fine.

