Комментарии:
The advice I've gotten was to use the anyhow crate non-library projects, and to properly template out error types for library code.
ОтветитьI use `Result<T, ()>` regularly. In fact I use it so often that I usually write `type Result<T> = result::Result<T, ()>;` at the top of my application code. The reason is that it makes error handling simpler. See example:
```rust
use std::result;
use std::fs;
type Result<T> = result::Result<T, ()>;
fn read_csv_of_floats(file_path: &str) -> Result<Vec<Vec<f32>>> {
let contents = fs::read_to_string(file_path).map_err(|err| {
eprintln!("ERROR: could not read file {file_path}: {err}");
})?;
let mut ret = Vec::new();
for line in contents.split('\n') {
let mut floats = Vec::new();
for cell in line.split(',') {
floats.push(cell.parse::<f32>().map_err(|err| {
eprintln!("ERROR: could not parse {cell:?} as float: {err}");
})?;
}
ret.push(floats);
}
Ok(ret)
}
fn entry() -> Result<()> {
let csv = read_csv_of_floats("data.csv")?; // Main doesn't have to worry about logging errors anymore
// do something with csv
}
fn main() -> process::ExitCode {
match entry() {
Ok(_) => process::ExitCode::EXIT_SUCCESS,
Err(_) => process::ExitCode::EXIT_FAILURE,
}
}
```
Does this mean there is, or should be, a way to safely convert a Result<T, Infallible> to a T without having to handle the impossible Infallible case?
ОтветитьNice video! I'll add that for fans of Haskell (and/or Scala), Rust has a do_notation crate that allows you to work with monads in a similar way.
Ответитьwhy not just escalate the error within the type, an enum on parent/grandparent which is inherently a recursive call/trait...
seems silly python has raise r escalate as key
word, this type error could easily be extended with attribute frace and could just append to the stack call error.
i hope this is what we will get into with the final 4 minutes bc this grandparent error as distinct enum is silly... although i liked the surfacing like visibility
... also please introduce "become" as a keyword for cto, that would make me never want to leave the language again.
Me when I first saw Result<T, E> and didn't know how it worked:
pub fn testing() -> Result<(), Result<(), Result<(), Result<(), Result<(), the list goes on...>>>>>
This is great. For the last section using infallible, besides teaching us about infallible is there any reason to avoid a bool return type instead of result<bool, …>
ОтветитьWould the compiler know the error state won't be reached if it's infallible?
ОтветитьWhat’s a turbo fish
ОтветитьThis is the future of learning
ОтветитьThis almost makes me wish I knew Rust. Almost.
ОтветитьFANTASTIC VID! You explained hidden corners of the language that I've not seen other tut makers cover. Kudos and thanks!!!
ОтветитьThank you for these in depth explanations!
ОтветитьUsing Manim for this is beautiful.
ОтветитьIf you want to convert Vec<Result<T>> to Vec<T> you can use .iter().flatten().collect()
Flattening before collecting is nice when it's acceptable for some items to fail
I mean this video is in itself infallible!
Thank you
So, just use Result.
ОтветитьWhat does one use to edit such videos?
Ответитьfk, such a good explanation, ty.
ОтветитьOuch - just starting in Rust and this is still too obscure to me - will have to go through this video more times than just one :)
ОтветитьI don't think you should consider Option::None as an "error".
It's more like you handle something which is can exist or not. None is acceptable when Result::Err isn't and you need to handle it properly. Keep the error or propagate it. But Result::Err is about managing failure.
this is very helpful, things I thought I knew I learned more about ... :-)
Ответитьa1 a1
ОтветитьThis might be pedantic but it was fun to learn about: Never isn't exactly the bottom type. It is an empty type, with no values, but the RFC making it a full type explicitly says that it isn't the bottom type, because it's not a subtype of anything. It coerces to any type, but it isn't a subtype of anything. And this is awesome news for us: otherwise Vec<!> would be a subtype of Vec<T> for any T, and that means we wouldn't be able to write to a Vec.
Subtyping in Rust is pretty much limited to lifetimes, which is what seems to allow stuff like Vec to be covariant in rust even though it would have to be invariant in a language like Kotlin.
I feel like result represents a genuine failure of the function more than option. For instance, HashSet::get does not always have a value for a certain key and that is expected behavior when consuming that API. In contrast, parsing a string and getting a UTF8Error is not something that you would expect to happen and signals that a genuine exception can happen. HashSet::get can not fail in the same way since a None return is expected behavior sometimes and not considered an error like a string parsing error. Do you agree?
ОтветитьI love the way you talk about hugely complex things in such a clean and clear, understandable way. One of the best rust channel on yt
ОтветитьI watch this video every time I'm about to write a library to remind myself how to do it right, and every time I learn and remember a bit more. My journey of errors was Box<dyn Error>, anyhow, thiserror, and I'm probably right in that most crustaceans go through this cycle lol. Great vid, thanks. Wish I had it when I started with rust.
ОтветитьYes please, more interesting Rust content
Ответитьnice work
ОтветитьInteresting interesting
ОтветитьWhat if there's more than one failure?
ОтветитьJust use C++ 🤷♂️
Ответитьconcise, easy to understand and straight to the point, you earned yourself a sub
ОтветитьWho the fuck calls std "stood"?
ОтветитьThis whole vid could be simplified by saying "abandon Result<...>, use int like C does you numnuts!"
*Edit:* if you REALLY want to limit the output then you could go the _BitInt(2) route, only 3 results possible from that.
Nice video! Thank you very much😂
Ответитьanother great high quality video
Ответитьi dont think the none option should be used to indicate failure, instead i like to think of it as indicating that the value youre asking for does not exist. HashMap::get returns none when theres no value for the given key. i think using a result (even when theres only 1 possible kind of error) when theres a chance the function fails makes more sense and is more readable
ОтветитьI was uncompfortable with Result<> for some time because of the confusing builtin syntax around the type not the Result<> type itself. There are so many different way of interacting with them like unwrap and ? and OK() and all that. It took me some time to actually find a resource that packed all the different ways of interacting with Result in one place and when to use which one. The result type propagation of ? was particularly confusing at first because it seems like implicit magic if you don't know what you are looking at.
That was some time ago now though (4 years or so). So I assume the explanations of this are probably much easier to find and well written compared to back then.
A node not having a grandparent is not an error. I disagree with the Result<&Node, Error> approach. Just return Some or None. Such a procedure should not even exist. parent(&node) should be enough. Easy and simple to test, use, nest, etc. Keep it simple.
Ответитьsimpler way but the vid is 20 minutes 😀
ОтветитьResult is not the alternative to exceptions in C++. C++ counterpart would be std::expected, Rust's counterpart of exceptions would be panic!, unwrap(), expect() and other calls (the ones I might forget, there seem to be too many of them) crashing your program if something goes wrong.
ОтветитьGreat tutorial, thank you. I second other comments: we would like more videos like this
ОтветитьThese explanations are high quality stuff.
ОтветитьVery nice! Thank you
ОтветитьHave I ever used Rust?: No.
Will I ever use Rust?: Probably not.
Do I know most of the things he is talking about?: Definitely not.
Did I enjoy the video?: Yes
1. How to convert a Result<T, Infallible> to just T ?
2. What's the difference between ! and Infallible