4 ms·
Go is sort of a cross between Python and C with a bunch of concurrency support and a fairly elegant design. It's small and low cognitive overhead, but at the e
by Symmetry 12y ago
Go is sort of a cross between Python and C with a bunch of concurrency support and a fairly elegant design. It's small and low cognitive overhead, but at the expense of certain types of expressiveness. It requires it's garbage collector, so it's hard to use it too far down the stack. It's gotten the most traction as a Python replacement, though I'd be happy to see it replacing Java in some cases too.
Rust is sort of like a cross between C++ and Haskell. It has better facilities for abstraction and enforced safety than Go, but at the cost of more cognitive overhead and being harder to learn. People who plan to use it generally use C++ now.
These languages are actually going after different use cases, and for my robot there are some parts of the codebase I'd write in Go if we were re-writing, and some in Rust.
- kzrdude 12y agoRust is also a bit like C (and not C++) by not having implicit calls to constructors, copy constructors etc, so its values are less magic.
- malandrew 12y agoLess magic is such a good value to have. You can always make magic from unmagic pieces, but it's not possible to de-magic-ify magic. For example, I really dug the decision to remove GC from the Rust language and move it to the standard library.
- pjmlp 12y agoHaving a GC as a library type means many optimizations that need compiler help are not possible unless the library types are "magic" to the compiler.
- kibwen 12y agoEven if the GC were in the language, the optimizations that you speak of would have negative performance ramifications on all code that did not use GC. The reason that we took the plunge and moved GC into the stdlib was because we weren't willing to make that sacrifice. It does mean that our GC will never be particularly optimal. And that's fine, because if you really need shared ownership you should be using our really great refcounted pointers instead. :)
- pjmlp 12y agoI used to agree with Rust approach, assuming the compiler does dataflow analysis to minimize needless refcounting. Now that the refcounting is also moved to a library, I am not sure. Or are those types known to the compiler and the respective optimizations applied?
- dbaupp 12y agoThey fall out automatically from move semantics, a reference count only occurs on an explicit clone call: fn just_a_ref(x: &T) { ... } fn rc_by_val(x: Rc<T>) { ... } fn rc_by_ref(x: &Rc<T>) { ... } let some_rc_pointer: Rc<T> = ...; just_a_ref(&*some_rc_pointer); // no ref counting rc_by_ref(&some_rc_pointer); // no ref counting rc_by_val(some_rc_pointer.clone()); // ref count incremented // last use of a value (statically guaranteed that // some_rc_pointer is never used again): rc_by_val(some_rc_pointer); // no ref counting
- pjmlp 12y agoThanks for the clarification.