Почему этот код работает?


#1

Имеется код

fn translate_char(c: &char) -> char{
    if c.is_numeric(){  return *c; }
    match c {
        &'Н' => 'V',
        &'П' => 'Z',
        _ => panic!("Can't translate char {}", c),
    }
}

Ссылки на уровне ассемблера - это же указатели, так? В моем понимании match должна сравнить по указателям, но она сравнивает по содержимому. Как так? Магия какая-то.


#2

Точно, это :sparkles:магия:sparkles:. Это заклинание называется pattern matching.
match ничего не сравнивает, он сопоставляет шаблону. Слева от стрелок находится не значение c которым сравнивается переменная, а шаблон которому сопоставляется значение переменной c.
Ссылки можно разбирать так же как и структуры (Деструктуризация).
Этот код полностью эквивалентен вашему примеру:

    match *c {
        'Н' => 'V',
        'П' => 'Z',
        _ => panic!("Can't translate char {}", c),
    }

К тому же в Rust операция сравнения (trait Eq) переопределена для ссылок и других указателей Box, Rc, Arc. Этот код выведет true:

    let a = 'A';
    let b = 'A';
    println!("{}", &a == &b);

Чтобы узнать на одно место указывают ссылки или нет, нужно преобразовать их в сырые указатели (raw ptr):

    let a = 'A';
    let b = 'A';
    println!("{}", &a as *const char == &b as *const char);

P.S. Ссылки не тоже самое, что ассемблерные указатели. Например, размеры ссылок на Sized и !Sized типы отличаются.


#3

тут про F#, но суть того как выполняется сопоставление с образцом примерно та же