Toward a more approachable Rust
Toward a more approachable Rust
Posted Feb 24, 2017 16:30 UTC (Fri) by excors (subscriber, #95769)Parent article: Toward a more approachable Rust
It seems many philosophical differences in Rust vs Go are similar to those in C++ vs Java. E.g. C++ doesn't really support strings in its core language; instead the language provides sufficiently powerful features for the standard library to implement a reasonable std::string type. In contrast, Java has explicit language support for strings: string literals are always java.lang.String objects, the "+" operator is overloaded for java.lang.String and nothing else, etc.
If you just want to use native strings, maybe the Java approach is a little nicer; you can write "foo"+"bar" and get sensible behaviour, whereas C++ needs you to express a conversion to std::string first. The bigger difference is when you *don't* want to use the native strings. You might realise that java.lang.String is UTF-16 which nowadays is a stupid representation for strings, but there's absolutely nothing you can do about it. It's a historical mistake in the language design that application developers are stuck with forever.
In C++, since there's nothing special about the standard library, you can easily replace std::string with your own better string type for your particular use case (and many large applications do so, often with multiple string types optimised for different uses). If you want to use a validity-checked UTF-8 representation, you can do that. If you want to automatically switch between ASCII and UTF-32 representations depending on the content of the string, that's fine. If you want to use a rope data structure, no problem. You have access to operator overloading and templates and implicit constructors over string literals and so on, so your new type is not disadvantaged compared to std::string.
Similarly, Go has a built-in map type with special language support. If you want something slightly different, e.g. an ordered map or a thread-safe one or a higher-performance one, then (as far as I'm aware) you have to implement a custom type that can only support syntax like foo.Get("bar") and not foo["bar"], so it's syntactically inferior to the built-in type. In C++ and Rust the standard library has hash maps, but they're not a special part of the core language, so you can reimplement them without being demoted to a second-class citizen.
For average unadventurous programs, the Java/Go approach of trusting the language designers to provide decent data structures and concurrency features is probably fine; they're pretty smart people and it'd take a lot of effort to do better. But it's likely they made tradeoffs that aren't optimal for your specific application, or decisions that turn out to be mistakes with a couple of decades of hindsight. Even if you're smart enough and willing to put in the effort to do better, the language constrains you. The C++/Rust approach of having a small but powerful core language, with most features going into libraries that application developers can rewrite and replace when necessary, removes that constraint - if your application is valuable enough to deserve the extra investment of effort then you can keep improving it and get a better result in the long term.
(But NTPsec sounds (based on very limited knowledge) like a fairly small program without demanding performance requirements that sits in Go's primary niche of networked servers, and its developers are coming from C not C++, so it probably wouldn't get the benefits of Rust's philosophy and may do better with Go.)
Posted Feb 27, 2017 18:41 UTC (Mon)
by davidstrauss (guest, #85867)
[Link]
The memory model of encapsulated data is becoming more formalized in C++17 with contiguous iterators. If code consuming a data structure expects to use such iterators (as they might choose to with std::string), you would not be able convert the underlying structure to use a rope.
This is not usually a problem for existing code, as prior standards for C++ had no concept of a data structure promising contiguous memory, but std::string and similar STL data structures have guaranteed that model in a way that hasn't been compiler-enforced (but that programmers could assume). The danger here is updating old code that relies on the properties of something like std::vector with something that doesn't guarantee contiguous iterator use. I could see this happening because the pre-C++17 code had no way to formally require such properties from a data structure (and so one might assume code not requiring it in the C++17 way doesn't need it).
Toward a more approachable Rust