Change output type of Bufreader or input type of function


This is probably a stupid easy question but I have been able to solve it by googling yet.

I am reading in a txt file line by line using Bufreader then using that output to feed into a loop and using a crate called "distance" that calculates the hamming distance between to inputs. The problem I am running into is the the hamming function wants $str as input but the Bufreader is generating either a String or emun "result".

So basically how do I change a String to a $str

//collecting arguments 
    let args: Vec<String> = env::args().collect();

//assigning arguments to variables
    let query = &args[1];
    let file_path = &args[2];

//printing info about arguments
    println!("Searching for {}", query);
    println!("In file {}", file_path);

//assign file pathe to variable
    let file = File::open(file_path).unwrap();

//put file into buffer
    let reader = BufReader::new(file);

//iterate over buffer line by line
    for line in reader.lines() {
        println!("Line: {}", line.unwrap());
        let distance = hamming(line_1, "ACTGATTC").unwrap();
        println!("hamming distance: {}", distance)

The error output

error[E0308]: mismatched types
  --> src/
29 |         let distance = hamming(line, "ACTGATTC").unwrap();
   |                        ------- ^^^^ expected `&str`, found enum `Result`
   |                        |
   |                        arguments to this function are incorrect
   = note: expected reference `&str`
                   found enum `Result<String, std::io::Error>`
note: function defined here
  --> /Users/joshua.hill/.cargo/registry/src/
38 | pub fn hamming(s: &str, t: &str) -> Result<usize, DistanceError> {
   |        ^^^^^^^

Again this is probably a trivially easy thing to do but I cannot seem to get it. Learning a new language is hard.

Thanks for your time.

You can either provide a reference to a String (thanks to its implementation of Deref<Target=str>, allowing the compiler to implicitly dereference a String as a string slice str. This allows the compiler to coerce &String to &str) or, if you prefer to be more explicit, use the String::as_str method, which does exactly the same. So either:

let distance = hamming(&line.unwrap(), "ACTGATTC").unwrap();


let distance = hamming(line.unwrap().as_str(), "ACTGATTC").unwrap();

should work.

Because you are working with a Result, you can also use Result::as_ref to convert Result<String, _> to Result<&str, _>:

let distance = hamming(line.as_ref().unwrap(), "ACTGATTC").unwrap();

Thank you for that. All of those work! So the next question is which one would be the best for following some sort of best coding practices?

thanks for your help

I don't think you can make any mistakes here. Personally, I'd probably choose the last one to keep the operation that can panic (.unwrap()) as the last operation, making it easier to see while scanning your code quickly. If you were to handle the error case with a default value, for example, it would also be the handiest of the three, because line.as_ref().unwrap_or("ACTGA") is easier to reason about than &line.unwrap_or("ACTGA".to_owned()), for example.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.