8 ms·
The more I look at Rust the less I like the syntax, what are those? "Ok(())"
by Thaxll 10y ago
The more I look at Rust the less I like the syntax, what are those? "Ok(())"
- nemaar 10y agoIt's an empty tuple stuffed into an enum variant called Ok. The empty tuple plays the role of the traditional void.
- dikaiosune 10y agoImportantly, it's the Ok variant of the Result<(), SomeError> type, which is richer than a boolean because it carries information about why/where an operation failed, not just whether it succeeded or failed. It's similar to (but not identical to): public void someOperation() throws SomeException { ... }
- cfallin 10y agoI like to compare it to the "comma error" idiom in Go, i.e., `result, err = doStuff(...)`. The Rust prelude's Result enum is a less ad-hoc version of that.
- dikaiosune 10y agoRight, and the Rust result also produces a compile-time warning (which can be escalated to an error) if the value isn't checked.
- yarper 10y agoIt supports that kind of error handling too, fn something() -> (String, String) ... let (result, err) = something() It's just that Result is preferable because you can pattern match on it
- kazagistar 10y agoThat would be fn something() -> (Option<String>, Option<String>) Because the Rust types aren't nullable by default. But that more clearly demonstrates that Result types are better since they enforce that the error and result are mutually exclusive.
- yarper 10y agoagreed!
- pcwalton 10y ago() is the unit/void value. The void value isn't a concept that most languages have, so the syntax may be unfamiliar, but it's really useful and once you have it it's annoying to work with languages that don't have it.
- nostrademons 10y agoIt's actually fairly common in modern languages, particularly in expression-oriented languages. Haskell, Ocaml, Swift, and Scala spell it (). Python spells it None. Kotlin spells it Unit(). In Kotlin and Python, it is implied whenever you do 'return' without a value, which is a pretty handy way of bridging programmers' understanding of it when they come from older programming languages (eg. Java and C) that don't have it.
- Jweb_Guru 10y agoPython's None is closer to null than unit.
- adrusi 10y agoThere isn't really a meaningful distinction in a dynamically typed language. Null is a value that indicates the absence of something else that could be there instead, Unit is essentially the lack of any value. So when a python function implicitly returns None whenever it's called, that's semantically more similar to Unit than Null.
- kazagistar 10y agoThe difference is methods. A Result or Option has methods like map that let you transform it regardless of which case it is in, while a null will always crash unless you match on it first.
- adrusi 10y agoIn that case, do you condsider Go's nil to not be a null, since you can call methods on it that can do whatever? Or how about objective C's nil, where any messages sent to it are simply ignored? Edit: I see now that you're talking about the difference between null and Result/Option, not the difference between null/Option and Unit, so we're talking about different things. Semantically, a value that could be data or null is equivalent to an option type. Option types have methods, yes, but that's just a superficial convenience facility, you could implement the same thing for nullable types by writing a function: public static <A, B> B map(A object, Function<A, B> f) { if (object == null) return null; return f.apply(object); }
- pornel 10y agoThere are some eye-poking bits in Rust's syntax, but this one is not so bad. `Ok(value)` makes an instance of the `Result` type. Imagine `struct Result Ok(some_t value);` in C. `()` is a 0-length case of a tuple. Sort-of like `{}` in C's `int arr[] = {}`. It's used here, because `Ok` is defined to take a value, so something must be provided. The compiler knows how to optimize out `()` completely, so the single `Result` type can be used for efficiently handling both cases returning a something||error and NULL||error.
- lossolo 10y agoOr this: pub fn from_bytes(bytes: &'a [u8]) -> IResult<&'a [u8], C<'a>> { ... } or something like this: fn parse_response<'a>(bytes: &'a [u8]) -> IResult<&'a [u8], C<'a>> { switch!(bytes, tuple!(be_u32, be_u32), (::CONNECT_ACTION_ID, tid) => map!(be_u64, |cid| B::new(tid, ResponseType::Connect(cid)) ) | (::ANNOUNCE_IPV4_ACTION_ID, tid) => map!(call!(W::from_bytes_v4), |ann_res| { C::new(tid, ResponseType::Announce(ann_res)) }) |
- steveklabnik 10y agoYou're missing a <'a> in the declaration there ;) "from_bytes is a public function with one lifetime parameter, a. It takes one argument, a slice of u8 with the lifetime 'a, and returns an IResult, which gives back a slice of u8 with the lifetime 'a in the success case, and some type C, which is also parameterized with the lifetime 'a, in the failure case." This is not really normal rust code; it's nom, which is a very macro-heavy DSL. There are decent upsides, and I love nom, but its downside is that it does look a bit odd.
- nitrogen 10y agoIt would be amazing if there were a parser that would translate Rust declarations into english. I think something like that exists for C, but I can't recall the name or how effective it is.
- steveklabnik 10y agohttp://cdecl.org/ http://cdecl.org/
- Sammi 10y agoIt doesn't look a bit odd. It looks impenetrable.
- steveklabnik 10y agoWell, without all the whitespace, it is ;)
- educar 10y agoI get what you are saying. The code is not very readable for an engineer well-versed is C-style languages. That said, I was a systems engineer and did a lot of C++ but now don't really understand it anymore because these days it's incomprehensible to me especially after c++11/14 (and I coded in c++ for many years!). Same goes for javascript - with es7, the language syntax is changing very much (and imo, not for the better). They just keep adding features for no reason. I just hate that languages at some point try to behave they are some sort of library with non-stop changes :/ So, despite not liking Go syntax, I like the people behind Go. They don't want to change it too much for no reason (yes yes, we need generics). I like that philosophy. In fact, C is pretty much the only language which has held on to it's core syntax to me.