3 ms·
Not really. Hiding the data is the easy part. What makes Rust special is that you need to acknowledge the potential errors when unwrapping the type. With a sta
by ViewTrick1002 1y ago
Not really. Hiding the data is the easy part.
What makes Rust special is that you need to acknowledge the potential errors when unwrapping the type. With a standard library and culture built on exposing the edge cases at compile time.
That is where the guarantees and feeling of certainty comes from.
- lock1 1y agoVisibility modifier as a native language feature is not the easy part. It's more like "comptime safety feeling" => "language w/ visibility modifier" but the converse is not necessarily true. Without language support, it's back to C convention or workaround again.
- menaerus 1y agoShow me an example. I don't understand this marketing lingo.
- ViewTrick1002 1y agoTake for example working with file names and paths. In for example Linux paths are a collection and bytes and does not need to be valide unicode. Which some programming languages hides from you and subtly introduces errors. Or even worse, accepting that strings may contain invalid unicode poisoning the entire language with uncertainty. If you are iterating over the files in a directory the Rust standard library gives you paths. Not strings. To convert a path that to a regular string type which is valid unicode you need to acknowledge that the path may be invalid. Either unwrapping and panicking or handling the error. To do this the standard library gives two options: /// Yields a [`&str`] slice if the `Path` is valid unicode. /// /// This conversion may entail doing a check for UTF-8 validity. /// Note that validation is performed because non-UTF-8 strings are /// perfectly valid for some OS. pub fn to_str(&self) -> Option<&str> https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.to_str https://doc.rust-lang.org/std/path/struct.PathBuf.html#metho... Or accept that the conversion may be lossy: /// Converts a Path to a Cow<str>. /// /// Any non-UTF-8 sequences are replaced with U+FFFD REPLACEMENT CHARACTER. pub fn to_string_lossy(&self) -> Cow<'_, str> https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.to_string_lossy https://doc.rust-lang.org/std/path/struct.PathBuf.html#metho... You get to make a choice, and panicking/erroring is perfectly valid if you only expect valid unicode paths. As the world and your software changes if you suddenly encounter a non-unicode path then you will immediately know where the error comes from and can fix the issue. Instead of trying to pinpoint the root source of an error far exposing itself far down stream.
- menaerus 1y agoYou said > With a standard library and culture built on exposing the edge cases at compile time. So, how exactly is "you need to acknowledge that the path may be invalid" from your example a compile-time trait? That's certainly not something you know during the compile-time, and if so, then you should be treating all the files like that, so, I see no difference here wrt other languages.
- ViewTrick1002 1y agoTake the function signature: pub fn to_str(&self) -> Option<&str> An option is an enum (tagged union) pub enum Option<T> { None, Some(T), } To get the data out of the Some variant you need to match on it. If you don't cover the the None variant with a choice it will not compile. let my_valid_string = match path.to_str() { Some(path) => path, None => todo!("Cover invalid unicode case"), } You can see this in the playground here were I deliberately did not cover the None path leading to the compiler telling me I need to make a choice. https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&gist=1f335ca9b0ddae1a5093ace149be0c0d https://play.rust-lang.org/?version=stable&mode=debug&editio... We can't know if a generic path is valid at compile time. But we can at compile time ensure that we must acknowledge and make a choice for the invalid case. This now (in)famous blogpost on Go is what happens when you just pretend that everything works: https://fasterthanli.me/articles/i-want-off-mr-golangs-wild-ride https://fasterthanli.me/articles/i-want-off-mr-golangs-wild-...
- johnisgood 1y agoOCaml, Haskell, Kotlin, and Swift has this, too...
- scns 1y agoThere are at least some unikernels written in OCaml IIRC, don't know about kernells written in Haskell.
- jeroenhd 1y agoThat's not a language feature as much as it is a culture and standard library feature. For instance, Java could do the same, but in practice conversion methods throw runtime exceptions that you won't be warned about and your code will randomly crash if conversions fail, except in some cases when it doesn't. For casting between numeric types the language does have some legacy cruft, but for web applications nothing is stopping you from doing this. Java's explicit exception system is great at forcing developers to deal with potential failures, but in practice Java developers chose not to deal with exceptions so often that exceptions now get hidden. Rust does this stuff in the standard library and that gives you the advantage that you don't need to explain the concept and convince every developer that this is a good idea. The same way Java has optional nullability annotations that are rarely used in practice because not every developer feels like adding them, unlike languages where nullability is part of the type system. The concept is not exclusive to Rust, but I also haven't found it very popular outside of Rust developer circles.
- baq 1y agoI'm happily using this pattern in TS to wrap DB ids to avoid mistakenly passing e.g. user id to a function accepting a thing id or vice versa. Works very well and prevented a few close calls. I'd call it a type system feature, especially if you pack the id in a nominal type.
- cleartext412 1y ago> Java's explicit exception system is great at forcing developers to deal with potential failures, but in practice Java developers chose not to deal with exceptions so often that exceptions now get hidden. Every time I see someone bringing up the idea of adding checked exceptions to a language (usually in these endless exceptions vs returning errors debates), it is met with "it won't work, look at Java", and it feels like a real shame. I'm sure complications of additional syntax would pay off just as fast as it does for regular type annotations.