#Curious about '?' operator

40 messages · Page 1 of 1 (latest)

median shell
#

Trying to do some CSV reading, and a tutorial i found used the ? operator after a couple function calls, namely

let mut rdr = ReaderBuilder::new().has_headers(true).from_path(csv_path)?;

and

for result in rdr.records() {
        let record = result?;

but this throws errors, saying that the functions do not return the proper type "the ? operator can only be used in a function that returns Result or Option (or another type that implements FromResidual)" and im curious about a potential fix or why this happens

twilit yoke
#

-?

atomic masonBOT
#
let contained_value = fallible_function()?;
``` is equivalent to ```rs
let contained_value = match fallible_function() {
  Ok(val) => val,
  Err(err) => return Err(From::from(err)),
};
median shell
#

ah, got it thank you! is there any reason this won't work for a function that does return type

Result<StringRecord, Error>

is there some other step i have to take?

#

i guess my main question is that this seems like the ? says it will work for functions returning some Result, but when i give it something that seems to fulfill that
such as

    let mut rdr = ReaderBuilder::new().has_headers(true).from_path(csv_path);

adding the question mark at the end will cause errors saying that cant be done for function that returns ()

keen heath
#

can you post the full error message?

twilit yoke
#

cant be done for function that returns ()
then the function you're using ? in returns ()

median shell
#
error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`)

for line

    let mut rdr:= ReaderBuilder::new().has_headers(true).from_path(csv_path)?;
keen heath
#

the full error message

twilit yoke
median shell
#
fn main() {

    
    let csv_path = "data/penguins.csv";

    let mut rdr:= ReaderBuilder::new().has_headers(true).from_path(csv_path)?;

    let mut x: Vec<Vec<f64>> = Vec::new();
    let mut y: Vec<f64> = Vec::new();

    for result in rdr.records() {
        let record: StringRecord  = result?;
        
        let label: f64 = match record.get(0) {
            Some("Adelie") => 0.0,
            Some("Chinstrap") => 1.0,
            Some("Gentoo") => 2.0,
            _ => continue,
        };

        let features: Vec<f64> = (2..6)
            .filter_map(|i| record.get(i).and_then(|v| v.parse::<f64>().ok()))
            .collect();

        if features.len() == 4 {
            y.push(label);
            x.push(features);
        }
    }
}

here is more of the code

median shell
glossy knoll
atomic masonBOT
#

Run cargo check in a terminal

Note: If using rust analyzer you can click the "click for full compiler diagnostic" link in your editor.

Please post the full output of the above command, including the error title and any help or notes. An example of how this looks is:

error[E0308]: mismatched types
 --> src/main.rs:3:17
  |
3 | let foo: &i32 = bar;
  |          ----   ^^^ expected `&i32`, found integer
  |          |
  |          expected due to this
  |
help: consider borrowing here
  |
3 | let foo: &i32 = &bar;
  |                 +

When posting the error put it in a code block so it has nice formatting:

```rust
// error from cargo check here
```

Please do not post a screenshot. If the output is too long then use a paste tool like https://paste.rs/web

keen heath
#

yes, at least anything that's not clearly unrelated

twilit yoke
median shell
# atomic mason ### Run `cargo check` in a terminal Note: If using **rust analyzer** you can cli...

error[E0277]: the ? operator can only be used in a function that returns Result or Option (or another type that implements FromResidual)
--> src/main.rs:19:76
|
14 | fn main() {
| --------- this function should return Result or Option to accept ?
...
19 | let mut rdr= ReaderBuilder::new().has_headers(true).from_path(csv_path)?;
| ^ cannot use the ? operator in a function that returns ()
|
= help: the trait FromResidual<Result<Infallible, csv::Error>> is not implemented for ()
help: consider adding return type
|
14 ~ fn main() -> Result<(), Box<dyn std::error::Error>> {
15 |
...
53 | println!("Predictions: {:?}", predictions);
54 + Ok(())
|

error[E0277]: the ? operator can only be used in a function that returns Result or Option (or another type that implements FromResidual)
--> src/main.rs:25:43
|
14 | fn main() {
| --------- this function should return Result or Option to accept ?
...
25 | let record: StringRecord = result?;
| ^ cannot use the ? operator in a function that returns ()
|
= help: the trait FromResidual<Result<Infallible, csv::Error>> is not implemented for ()
help: consider adding return type
|
14 ~ fn main() -> Result<(), Box<dyn std::error::Error>> {
15 |
...
53 | println!("Predictions: {:?}", predictions);
54 + Ok(())
|

For more information about this error, try rustc --explain E0277.

median shell
#

?

twilit yoke
#

that is one way

median shell
#

is there a more recommended way?

glossy knoll
#

i dont usually use ? in main at all

keen heath
#

if you don't want to have to worry about error types too much a common recommendation is to use anyhow::Error from the anyhow crate

glossy knoll
#

and handle it other ways

keen heath
#

instead of Box<dyn Error>

median shell
glossy knoll
#

well you need to ask yourself what should happen if there's an error. do you want to explode and panic? do you want to handle the error then continue the program? or do you want to show an error to the user and gracefully exit?

keen heath
#

for the record there's not really much difference between doing ? in main and just calling .unwrap() on the result, both will cause the application to exit and print the error to the terminal

#

(in other functions than main there is a difference, however)

#

but if you want to handle the error more gracefully you can eg do a match on the result, and have different logic based on whether you got an Ok(..) or an Err(..) value

glossy knoll
median shell
#

thanks for everything!

gray bobcat
keen heath
#

it's not great, you're throwing away a lot of information

#

but more than anything anyhow just makes it easier to do things like add extra context, and are easier to work with in general

#

and of course if you're writing a library you should use neither, and should stick to something like thiserror or snafu instead of erasing the error type

gray bobcat
glossy knoll
#

rust does not have instrospection

keen heath
#

the most rust supports out of the box in terms of runtime introspection is downcasting from a dyn Any to a concrete type, if you already know what the target type is