<story><title>Ownership and Borrowing in D</title><url>https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in-d/</url></story><parent_chain><item><author>coder543</author><text>The problem with D is that it is so non-uniform. People talk about the betterC mode, but not nearly all D code written can run in this mode. Now people will talk about this ownership mode, but very little code will really use it. To become an expert in D or C++, you really need to understand what feels like a dozen different languages... and that’s not what I’m looking for in a single language.&lt;p&gt;D’s concept of ownership (for now) doesn’t seem to have any plan to support partially moved structs, which are a major ergonomic feature.&lt;p&gt;D has organically grown just about every interesting feature ever conceived, but I would much rather use a purpose-built language, which is what Rust feels like.&lt;p&gt;I don’t want a C++ that’s better at being C++ than C++ is. I really enjoy how consistent and expressive Rust is. I also appreciate how intentional Go is about being Go.&lt;p&gt;A lot of people enjoy C++, and some people enjoy D. I enjoyed C++ back when Rust wasn’t an option... then something better came along. D and C++ try to be everything to everyone. I like D better than C++... but I have seen no compelling reason to trade Rust for D.&lt;p&gt;Variadic templates are much better expressed by either tuples or const generics. A fixed length array of a constant generic length is the Rustic solution to tensor-like problems, and it is being rigorously developed.&lt;p&gt;Arbitrary compile time computation should be separated from the body of the program. If you need to download files or read the file tree at compile time, that should happen in a build script. Rust provides build.rs for that. Precomputing values without I&amp;#x2F;O is conceptually just an advanced kind of compiler optimization, and that’s why Rust is basically seeking to make const fns only pure functions.&lt;p&gt;The fast compile times are a double edged sword, since those binaries are noticeably slower than Rust binaries, from what I’ve seen. I hope that Rust will one day have a much faster compiler for development builds.&lt;p&gt;I also think every sign is showing that Rust is starting to get some real traction, so I don’t think I’m alone in these opinions... but they are mostly just that: opinions. You’re welcome to your own.</text></item><item><author>logicchains</author><text>If D manages to implement sound borrowing checking this will be huge! Brings it a step closer to matching Rust&amp;#x27;s feature list.&lt;p&gt;- Zero-cost abstractions: Yes!&lt;p&gt;- Move semantics: Yes!&lt;p&gt;- Guaranteed memory safety: Yes! (in code marked with the appropriate annotations)&lt;p&gt;- Threads without data races: Yes!&lt;p&gt;- Trait-based generics: No!&lt;p&gt;- Pattern matching: No! (Although like C++, in can be done as a library: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;code.dlang.org&amp;#x2F;packages&amp;#x2F;sumtype&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;code.dlang.org&amp;#x2F;packages&amp;#x2F;sumtype&lt;/a&gt;)&lt;p&gt;- Type inference: Yes! (Plus unlike Rust, you can also mark function return types auto, and let them be inferred too).&lt;p&gt;- Minimal runtime: Yes! (the GC could be disabled if using exclusively borrow-checked code)&lt;p&gt;- Efficient C bindings: Yes!&lt;p&gt;D also brings some features of its own to the table that Rust doesn&amp;#x27;t yet match.&lt;p&gt;- Higher-kinded types (template template params): it&amp;#x27;s possible to implement Haskell-style monads etc. in D, if for some reason you felt the need.&lt;p&gt;- Pure functions: these allow you to statically guarantee that a piece of code doesn&amp;#x27;t perform any IO and is a completely deterministic function of its inputs. This makes reasoning about a large codebase much easier, compared to Rust where there&amp;#x27;s no way to statically guarantee a function isn&amp;#x27;t doing any IO.&lt;p&gt;- Fast compile times: the reference DMD compiler is almost as fast as the Go compiler, at least for code that doesn&amp;#x27;t do a bunch of compile-time calculation.&lt;p&gt;- Compile-time compute: Rust now has constfn, but that still only supports a limited subset of the language. D allows almost the entire language to be used at compile time.&lt;p&gt;- Variadic templates: Something C++ users might miss when coming to Rust, they allow for the creation of things like tensors of arbitrary dimension (myTensor&amp;lt;6, 3, 2, 5, 6, 20&amp;gt;) on which operations are checked at compile time to ensure sizes are compatible (so it&amp;#x27;s a compiler error if you try to multiply two tensors of the wrong size or wrong number of dimensions).</text></item></parent_chain><comment><author>WalterBright</author><text>&amp;gt; Arbitrary compile time computation should be separated from the body of the program.&lt;p&gt;Here&amp;#x27;s some code that initializes an array at compile time with a non-trivial computation:&lt;p&gt;&lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;dlang&amp;#x2F;dmd&amp;#x2F;blob&amp;#x2F;master&amp;#x2F;src&amp;#x2F;dmd&amp;#x2F;backend&amp;#x2F;var.d#L293&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;dlang&amp;#x2F;dmd&amp;#x2F;blob&amp;#x2F;master&amp;#x2F;src&amp;#x2F;dmd&amp;#x2F;backend&amp;#x2F;var...&lt;/a&gt;&lt;p&gt;This used to be initialized by a separate program that generated some .d files. It was nice to get rid of that. Even better, if you check the generated object file, there&amp;#x27;s no trace of the code used to generate the array - just the data for the array.</text></comment>
<story><title>Ownership and Borrowing in D</title><url>https://dlang.org/blog/2019/07/15/ownership-and-borrowing-in-d/</url></story><parent_chain><item><author>coder543</author><text>The problem with D is that it is so non-uniform. People talk about the betterC mode, but not nearly all D code written can run in this mode. Now people will talk about this ownership mode, but very little code will really use it. To become an expert in D or C++, you really need to understand what feels like a dozen different languages... and that’s not what I’m looking for in a single language.&lt;p&gt;D’s concept of ownership (for now) doesn’t seem to have any plan to support partially moved structs, which are a major ergonomic feature.&lt;p&gt;D has organically grown just about every interesting feature ever conceived, but I would much rather use a purpose-built language, which is what Rust feels like.&lt;p&gt;I don’t want a C++ that’s better at being C++ than C++ is. I really enjoy how consistent and expressive Rust is. I also appreciate how intentional Go is about being Go.&lt;p&gt;A lot of people enjoy C++, and some people enjoy D. I enjoyed C++ back when Rust wasn’t an option... then something better came along. D and C++ try to be everything to everyone. I like D better than C++... but I have seen no compelling reason to trade Rust for D.&lt;p&gt;Variadic templates are much better expressed by either tuples or const generics. A fixed length array of a constant generic length is the Rustic solution to tensor-like problems, and it is being rigorously developed.&lt;p&gt;Arbitrary compile time computation should be separated from the body of the program. If you need to download files or read the file tree at compile time, that should happen in a build script. Rust provides build.rs for that. Precomputing values without I&amp;#x2F;O is conceptually just an advanced kind of compiler optimization, and that’s why Rust is basically seeking to make const fns only pure functions.&lt;p&gt;The fast compile times are a double edged sword, since those binaries are noticeably slower than Rust binaries, from what I’ve seen. I hope that Rust will one day have a much faster compiler for development builds.&lt;p&gt;I also think every sign is showing that Rust is starting to get some real traction, so I don’t think I’m alone in these opinions... but they are mostly just that: opinions. You’re welcome to your own.</text></item><item><author>logicchains</author><text>If D manages to implement sound borrowing checking this will be huge! Brings it a step closer to matching Rust&amp;#x27;s feature list.&lt;p&gt;- Zero-cost abstractions: Yes!&lt;p&gt;- Move semantics: Yes!&lt;p&gt;- Guaranteed memory safety: Yes! (in code marked with the appropriate annotations)&lt;p&gt;- Threads without data races: Yes!&lt;p&gt;- Trait-based generics: No!&lt;p&gt;- Pattern matching: No! (Although like C++, in can be done as a library: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;code.dlang.org&amp;#x2F;packages&amp;#x2F;sumtype&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;code.dlang.org&amp;#x2F;packages&amp;#x2F;sumtype&lt;/a&gt;)&lt;p&gt;- Type inference: Yes! (Plus unlike Rust, you can also mark function return types auto, and let them be inferred too).&lt;p&gt;- Minimal runtime: Yes! (the GC could be disabled if using exclusively borrow-checked code)&lt;p&gt;- Efficient C bindings: Yes!&lt;p&gt;D also brings some features of its own to the table that Rust doesn&amp;#x27;t yet match.&lt;p&gt;- Higher-kinded types (template template params): it&amp;#x27;s possible to implement Haskell-style monads etc. in D, if for some reason you felt the need.&lt;p&gt;- Pure functions: these allow you to statically guarantee that a piece of code doesn&amp;#x27;t perform any IO and is a completely deterministic function of its inputs. This makes reasoning about a large codebase much easier, compared to Rust where there&amp;#x27;s no way to statically guarantee a function isn&amp;#x27;t doing any IO.&lt;p&gt;- Fast compile times: the reference DMD compiler is almost as fast as the Go compiler, at least for code that doesn&amp;#x27;t do a bunch of compile-time calculation.&lt;p&gt;- Compile-time compute: Rust now has constfn, but that still only supports a limited subset of the language. D allows almost the entire language to be used at compile time.&lt;p&gt;- Variadic templates: Something C++ users might miss when coming to Rust, they allow for the creation of things like tensors of arbitrary dimension (myTensor&amp;lt;6, 3, 2, 5, 6, 20&amp;gt;) on which operations are checked at compile time to ensure sizes are compatible (so it&amp;#x27;s a compiler error if you try to multiply two tensors of the wrong size or wrong number of dimensions).</text></item></parent_chain><comment><author>logicchains</author><text>&amp;gt;Arbitrary compile time computation should be separated from the body of the program. If you need to download files or read the file tree at compile time, that should happen in a build script. Rust provides build.rs for that.&lt;p&gt;This is an area we&amp;#x27;ll have to agree to strongly disagree. For me having support directly in the language is a huge improvement in ergonomics, compared to having to run a separate script. Compare e.g. generics in Go1 (which can only be done with separate build scripts at compile time) vs in any other language that has built-in generics. Also consider F# type providers, which guarantee at compile time the correctness of code querying a database (generate the schema&amp;#x2F;structs by querying the database at compile time). Certainly the same thing could be achieved by running a separate script as part of the build process, but I&amp;#x27;ve never seen a language actually implement that, probably because it&amp;#x27;d be much more painful.&lt;p&gt;&amp;gt;The fast compile times are a double edged sword, since those binaries are noticeably slower than Rust binaries, from what I’ve seen.&lt;p&gt;Note that D also has an LLVM-based compiler backend that is slower to compile but produces much faster code, which can be used for release builds.</text></comment>