3 ms·
> Being pragmatic is a very questionable claim. Its exact meaning varies from time to time, and a property that a certain people consider to be pragmatic can be
by CyberShadow 11y ago
> Being pragmatic is a very questionable claim. Its exact meaning varies from time to time, and a property that a certain people consider to be pragmatic can be considered to be not pragmatic by another people. It's mostly meaningless.
I disagree that it is meaningless. It's simply subjective. I've used D since 2006 and tried most new programming languages that appeared since, and it seems like they all tried to solve a specific problem (e.g. Go - concurrency, Rust - memory safety) while giving less attention to everything else.
> For example, for embedded devices D is a no-go from the beginning.
Existing D projects contradict that. They simply don't use the standard D runtime when it's not appropriate. Alternative runtimes exist. Rust users do the same thing:
http://mainisusuallyafunction.blogspot.com/2015/01/151-byte-static-linux-binary-in-rust.html http://mainisusuallyafunction.blogspot.com/2015/01/151-byte-...
> D and Rust have different kinds of expressiveness. While D has much better compile-time metaprogramming, how do you express affine type in D? In Rust affine type is very fundamental and we can utilize it to define the exact meaning of our programs.
Can you provide a good example of affine types and how they help with expressiveness?
My view of expressiveness in D does not stop at compile-time metaprogramming. For example, here's an excerpt from one of my programs:
http://dump.thecybershadow.net/fb6c5a080c7a42ecd8d1f062b58a540d/000000CF.txt http://dump.thecybershadow.net/fb6c5a080c7a42ecd8d1f062b58a5...
> How can a GC'ed language be faster than a non-GC'ed language?
It is entirely plausible. For example, deallocation/destruction can run in a background thread, heap compaction removes heap fragmentation and improves cache locality, and of course throwing away all memory after the program is done executing is very practical if the program would otherwise do little deallocating overall.
> Are you really sure D can outperform C in general cases?
I don't know what's going on there, but "higher-level" languages outperforming C is not that uncommon, for example due to stricter aliasing rules or SIMD array vector operations, or simply due to language or standard library facilities being readily available (e.g. STL or associative arrays) which would be cumbersome or impractical to write/maintain in C versions.
- yokohummer7 11y ago> Can you provide a good example of affine types and how they help with expressiveness? For example, let's say there's an HTTP server handler that must send each header line first, and finally send a body. So you should: conn.send_header("HTTP/1.1 200 OK"); conn.send_header("Connection: Close"); conn.send_header("Content-type: text/html"); conn.send_body("Hello, world!"); In Rust, you can construct the API so that you cannot call `send_body` before any occurrences of `send_header`. So if you do: conn.send_body("I'm sent first!"); conn.send_header("Content-type: text/html"); you will get a compile error. This greatly reduces the risk of having incorrect logic in your program. In this case Rust helps ensuring our intention: `send_body` can only be the last call of the request handler. I consider this a good example of expressiveness of Rust (and affine types).
- CyberShadow 11y agoThat's very cool. Do you have a link with more information? I couldn't find anything when searching for "rust affine types".
- yokohummer7 11y agoDISCLAIMER: I'm not well-versed in type theory at all, so take my words with a grain of salt. Unfortunately I haven't seen any comprehensive article that discusses affine types in terms of Rust. So I can't recommend a link to you, instead I'll try to explain them in my own words. Affine types are those whose values can only be used at most once. They are implemented in Rust as ownership and borrowing. In my example above, `send_header` borrows the `conn` variable, whereas `send_body` takes the ownership of the `conn` variable. As you lost the ownership of `conn`, you cannot use it anymore, thus resulting in a compile error. This is similar to C++'s move semantics, where you are not permitted to move the same value more than once. It is just that in C++ "move only once" is a convention, whereas in Rust it is enforced by the type system. In Rust, if you pass an argument by value, you're automatically using affine types. You cannot use the passed variable anymore. To "borrow" instead, you need to opt-out using references. So, the hypothetical API I mentioned above would be written as: fn send_header(&self, text: &str) { ... } fn send_body(self, text: &str) { ... } Note the difference of `&`. Finally, all of these aren't just hypothetical. The exactly same design is used in Hyper[1], which is an HTTP library, and in nickel[2], which is a web framework in Rust. If you look at the API doc you will see there is no '&' in the self parameter. That means it's passed by value, using affine types, and the ownership is transferred, so you cannot use the original variable anymore. I hope this helps. [1] http://hyper.rs/hyper/hyper/client/struct.RequestBuilder.html#method.send http://hyper.rs/hyper/hyper/client/struct.RequestBuilder.htm... [2] http://docs.nickel.rs/nickel/struct.Response.html#method.send http://docs.nickel.rs/nickel/struct.Response.html#method.sen...