4 ms·
Rust has smart type checking. The really smart stuff is (IMO) the beauty of the borrow checker. In PHP, modern typecheckers can verify that the first element a
by muglug 5y ago
Rust has smart type checking. The really smart stuff is (IMO) the beauty of the borrow checker.
In PHP, modern typecheckers can verify that the first element always exists on an array after an emptiness check:
if ($some_arr) {
echo reset($arr);
}
Whereas in Rust you have to explicitly unwrap:
if !some_vec.empty() {
print!("{}", some_vec.first().unwrap());
// .. more code
}
The Rust version requires you to use your intuition to figure out that `unwrap()` will never panic here.
In my Rust port I consistently rely on the PHP typechecker's knowledge of the equivalent code when using `unwrap()`, because it knows which array fetches are safe.
> At the cost of introducing a bug/technical debt.
At the cost of shipping a product!
-------
Edit: user ibraheemdev proposes this Rust equivalent which more closely matches the idealised pseudocode, and type-checks:
if let [first, ..] = &some_vec {
print!("{}", first);
// .. more code
}
It's preferable IMO to
if let Some(first) = some_vec.first() {
because the latter relies on a property of a non-empty vec, and checks that property, rather than checking the non-emptiness of the collection.
- ibraheemdev 5y agoYou can usually use pattern matching to get around a check followed by an unwrap. I would rewrite your example as: if let [first, ..] = &some_vec { print!("{}", first); // .. more code }
- muglug 5y agoThanks, I did not know about that particular solution — that adheres more closely to the idealised pseudocode than any of the other Rust alternatives.
- deleted 5y ago[deleted]
- deleted 5y ago[deleted]
- ob 5y agoRust noob here but couldn't you write if let Some(element) = some_vec.first() { println!("{}", element); // .. more code } and avoid the unwrap and the empty check? Edit: Added a `let` I had forgotten.
- kccqzy 5y agoExactly (well other than "if let" here.) Every time you have a Boolean if condition with an unwrap, it means you are not taking advantage of the type system.
- ob 5y agoThanks, added.
- muglug 5y agoYes, but IMO that makes the code a bit more abstract: You've left behind an explicit "is this collection non-empty" and you're instead relying on a property of a non-empty collection. The PHP version can also be written as if (($element = reset($some_arr)) !== null) { echo $element; } But that code is similarly divorced from the imaginary pseudocode equivalent
- saghm 5y ago> Yes, but IMO that makes the code a bit more abstract: > You've left behind an explicit "is this collection non-empty" and you're instead relying on a property of a non-empty collection. More abstract for who? I think virtually all Rust programmers would easily understand the `if let` snippet, virtually all PHP programmers would understand the PHP snippet, and virtually all programmers of any language would understand that a non-empty array has a first element. I'm not at all convinced that most programmers would correctly guess that a function called `reset` is used to access the first element in an array though.
- kccqzy 5y agoA collection is non-empty if and only if it has a first element. Therefore checking for non-emptiness is the same as checking for the existence of a first element.
- csomar 5y ago> The Rust version requires you to use your intuition to figure out that `unwrap()` will never panic here. You should not use `unwrap` in a production product. It's there for prototyping and I think it's a mistake they have it (though the language already requires a good upfront time investment as it is). Use `?` and have your error propagate accordingly to the top of the chain. Have your own error types and convert from other error types. if !some_vec.empty() { print!("{}", some_vec.first().unwrap()); // .. more code } I don't know why you would check the first element of a vector. Use Rust type system to your advantage, and don't "convert" PHP code into Rust. Re-design your program. Also you don't need to check that the Vector is empty if you are using "first". "first" returns an Option with None if your vector is empty. My guess is that you have yet to exhaust the idioms Rust offers and approaching it in a PHP-like manner. > > At the cost of introducing a bug/technical debt. > At the cost of shipping a product! Okay!
- verdagon 5y agoWe tried this style in one of Google Earth's packages for a while (using an internal C++ class similar to Rust's Result). So many operations could theoretically fail (e.g. indexing out of bounds or an expected key not existing) that pretty much every single function in that package returned a Result. These "unexpected" errors would just fly up the stack, manually unwinding it, because nobody could really do anything with them. Once we had that, I really questioned some of our policies. I can imagine a language where panics don't crash the entire application, but instead blast away the surrounding "region" of memory, leaving the rest of the program intact and able to keep running. Similar to catch_unwind, but if the language is aware of region boundaries, and only allows certain methods of communication between them, it would leave the rest of the memory in much more predictable possible states. It may sound surprising, but it's actually possible with the right language constructs (Erlang folks know what I'm talking about!) and that way, we could once again have panics for unexpected errors, and Results for expected errors.
- Too 5y agoSounds like what you want is how exceptions behave in most languages? Including c++?
- staticassertion 5y agoThat sort of "flow typing" is extremely cool and I'd love to see it added to Rust. Perhaps something like mypy's proposed TypeGuard.