Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between double quotes and single quotes in Rust

Tags:

rust

I was doing the adventofcode of 2020 day 3 in Rust to train a little bit because I am new to Rust and I my code would not compile depending if I used single quotes or double quotes on my "tree" variable

the first code snippet would not compile and throw the error: expected u8, found &[u8; 1]

use std::fs;

fn main() {
    let text: String = fs::read_to_string("./data/text").unwrap();
    let vec: Vec<&str> = text.lines().collect();
    let vec_vertical_len = vec.len();
    let vec_horizontal_len = vec[0].len();

    let mut i_pointer: usize = 0;
    let mut j_pointer: usize = 0;
    let mut tree_counter: usize = 0;

    let tree = b"#";
    loop {
        i_pointer += 3;
        j_pointer += 1;
        if j_pointer >= vec_vertical_len {
            break;
        }

        let i_index = i_pointer % vec_horizontal_len;
        let character = vec[j_pointer].as_bytes()[i_index];
        if character == tree {
           tree_counter += 1
        }
    }

    println!("{}", tree_counter);
}

the second snippet compiles and gives the right answer..

use std::fs;

fn main() {
    let text: String = fs::read_to_string("./data/text").unwrap();
    let vec: Vec<&str> = text.lines().collect();
    let vec_vertical_len = vec.len();
    let vec_horizontal_len = vec[0].len();

    let mut i_pointer: usize = 0;
    let mut j_pointer: usize = 0;
    let mut tree_counter: usize = 0;

    let tree = b'#';
    loop {
        i_pointer += 3;
        j_pointer += 1;
        if j_pointer >= vec_vertical_len {
            break;
        }

        let i_index = i_pointer % vec_horizontal_len;
        let character = vec[j_pointer].as_bytes()[i_index];
        if character == tree {
           tree_counter += 1
        }
    }

    println!("{}", tree_counter);
}

I did not find any reference explaining what is going on when using single or double quotes..can someone help me?

like image 378
Mlengcivil Avatar asked Dec 30 '22 13:12

Mlengcivil


1 Answers

The short answer is it works similarly to java. Single quotes for characters and double quotes for strings.

let a: char = 'k';
let b: &'static str = "k";

The b'' or b"" prefix means take what I have here and interpret as byte literals instead.

let a: u8 = b'k';
let b: &'static [u8; 1] = b"k";

The reason strings result in references is due to how they are stored in the compiled binary. It would be too inefficient to store a string constant inside each method, so strings get put at the beginning of the binary in header area. When your program is being executed, you are taking a reference to the bytes in that header (hence the static lifetime).

Going further down the rabbit hole, single quotes technically hold a codepoint. This is essentially what you might think of as a character. So a Unicode character would also be considered a single codepoint even though it may be multiple bytes long. A codepoint is assumed to fit into a u32 or less so you can safely convert any char by using as u32, but not the other way around since not all u32 values will match valid codepoints. This also means b'\u{x}' is not valid since \u{x} may produce characters that will not fit within a single byte.

// U+1F600 is a unicode smiley face
let a: char = '\u{1F600}';
assert_eq!(a as u32, 0x1F600);

However, you might find it interesting to know that since Rust strings are stored as UTF-8, codepoints over 127 will occupy multiple bytes in a string despite fitting into a single byte on their own. As you may already know, UTF-8 is simply a way of converting codepoints to bytes and back again.

let foo: &'static str = "\u{1F600}";
let foo_chars: Vec<char> = foo.chars().collect();
let foo_bytes: Vec<u8> = foo.bytes().collect();
    
assert_eq!(foo_chars.len(), 1);
assert_eq!(foo_bytes.len(), 4);

assert_eq!(foo_chars[0] as u32, 0x1F600);
assert_eq!(foo_bytes, vec![240, 159, 152, 128]);
like image 174
Locke Avatar answered Jun 05 '23 02:06

Locke