How to solve this type mismatch?


#1

I have this code.
I want to display my error text on the screen as written in the code on lines 29 and 34. How to solve this error when compiling? So far, I’m using return 1 instead of error (because the types are the same). How to solve this type mismatch? Thanks for help! :slight_smile:


#2

I changed you code a bit: https://gist.github.com/rust-play/ce50eada00aedf68780181cfff471378. Instead of using panic!() you could choose to exit the program with an error code, of course.


#3

Thank you, but this is not what I expect, I only need a text without panic (same story with .expect() method).


#4

I was lazy using panic!().

You can do

use std::process;
...
{
            println!("This is not a number!);
            process::exit(1);
}

#5

What do you think about this? (Don’t try to run it on the playground, it does not seem to like the standard input so much…)

I put the parsing inside a loop for every variable, and the loop brakes once the value can be parsed correctly.

Obviously, there is some bad code repetition, but it is just to show you a possible approach without modifying your code so much.


#6

Since I’m inexperienced this is a new approach for me, but this code will not be compiled and this is a problem. Maybe you can help me reorganize this program in the best way? All I need is:

  1. Rise in power
  2. If the user does not enter numbers, display his error on the screen (without panic)
  3. If there was an error, repeat the entry of the number again

Is there a good example of such a program?


#7

@enzovitaliy what @dodomorandi gave you works, just not on the playground since it cant read input

Im very new to rust myself, so wanted to try to, but removing the repetition @dodomorandi tolk you about

:slight_smile:

use std::io::{stdin, stdout, Write};

fn readln(s: &mut String) {
    stdin().read_line(s).unwrap();
}

fn pow(n: i128, p: i128) -> i128 {
    if p == 1 {
        return n;
    }

    n * pow(n, p - 1)
}

fn read_number_from_cmd(question: String) -> i128 {
    let number_result = loop {
        print!("{}", question);
        stdout().flush().unwrap();

        let mut number = String::new();
        readln(&mut number);

        match number.trim().parse() {
            Ok(number) => break number,
            Err(_) => println!("This is not a number!"),
        }
    };
    number_result
}

fn main() {
    let number = read_number_from_cmd("Enter the number: ".to_string());
    let power = read_number_from_cmd("Enter the power: ".to_string());

    let result = if power == 0 { 1 } else { pow(number, power) };

    println!(
        "\n# You entered \"{}^{}\" and this equals \"{}\"",
        number, power, result
    );
}



#8

Honestly, I don’t know what is the issue with playground and, as @vegarringdal already wrote, it compiles locally.

What I did not expect is the fact that using the build command on the playground is not working as well :thinking:


#9

@enzovitaliy
Im using vscode on windows, its really easy to install.

Using rls extension
image

Only missing live debugging on windows.

Picture of the code I posted in my post running

@dodomorandi I also noticed that “build” isnt working very well, like its trying to run it and inserts input all the time


#10

@dodomorandi, @vegarringdal, but how the function can return println! macros, if in fact it returns i128? It is interesting to understand why so? When in my source code I used println! macros I got an error. Thanks for help :slight_smile:


#11

It does not return the result from println! macro. :grinning:

Let’s analyse the code:

loop {
    print!("{}", question);
    stdout().flush().unwrap();

    let mut number = String::new();
    readln(&mut number);

    match number.trim().parse() {
        Ok(number) => break number,
        Err(_) => println!("This is not a number!"),
    }
}

In the very first line we start a loop. It will continue forever unless break, and can return a value.

But at the same time, it will not return anything until brake is used, therefore the Err(_) => println!("This is not a number!"), line is not actually breaking the loop.

You can say that the match is returning the result of println!, but at the same time it is not used (honestly I don’t know if println! returns something or not…).

So, when Ok is matched, the loop is break and a i128 is returned, otherwise it continues looping. If something is still unclear, feel free to ask :wink:

P.s.: the fact that the return type is i128 is only because it is what the function is returning, and this is sufficient to track back the return type of the parse() function.


#12

Thanks for the help and patience, it was very useful for me :wink:


#13

small update on vscode, also using this:

image

makes autocompletion work better
forgot it last post :slight_smile:


#14

@enzovitaliy

There are two interesting situations. In the loop example from vegarringdal the only way you get out of the loop is the statement

break number;

In the error case the println!() returns the unit type (), i.e. in plain words it returns nothing. As the error case doesn’t exit the loop this is ok. If however, println!() would have returned anything else than a unit type then the compiler would issue an error.

A second interesting case is when I told you you could use

let number = match number.trim().parse::<i128>() {
        Ok(n) => n,
        Err(_) => {
            println!("This is not a number!");
            process::exit(1);
        },
    };

This works only because process::exit() is a so called divergent function. Its signature is:

pub fn exit(code: i32) -> !

The exclamation mark ! indicates a divergent function which means it never returns. Therefore this could be used. If in my last example you comment out the process::exit(1) line then you get an error because you cannot assign number a unit type as it is a number.


#15

@enzovitaliy

Saw this today, very useful page to know about if you are not using a IDE ATM :slight_smile:
https://areweideyet.com