Tipos de Chave Alternativos/Personalizados

Beginner

This tutorial is from open-source community. Access the source code

Introdução

Neste laboratório, exploramos o uso de tipos de chave alternativos/personalizados no HashMap do Rust, que podem incluir tipos que implementam os traits Eq e Hash, como bool, int, uint, String e &str. Além disso, podemos implementar esses traits para tipos personalizados usando o atributo #[derive(PartialEq, Eq, Hash)], permitindo que eles sejam usados como chaves em um HashMap.

Nota: Se o laboratório não especificar um nome de arquivo, você pode usar qualquer nome de arquivo que desejar. Por exemplo, você pode usar main.rs, compilar e executar com rustc main.rs && ./main.

Tipos de chave alternativos/personalizados

Qualquer tipo que implemente os traits Eq e Hash pode ser uma chave em um HashMap. Isso inclui:

  • bool (embora não seja muito útil, pois existem apenas duas chaves possíveis)
  • int, uint e todas as suas variações
  • String e &str (dica: você pode ter um HashMap chaveado por String e chamar .get() com um &str)

Observe que f32 e f64 não implementam Hash, provavelmente porque erros de precisão de ponto flutuante tornariam seu uso como chaves de hashmap terrivelmente propenso a erros.

Todas as classes de coleção implementam Eq e Hash se o tipo contido também implementar, respectivamente, Eq e Hash. Por exemplo, Vec<T> implementará Hash se T implementar Hash.

Você pode facilmente implementar Eq e Hash para um tipo personalizado com apenas uma linha: #[derive(PartialEq, Eq, Hash)]

O compilador fará o restante. Se você quiser mais controle sobre os detalhes, pode implementar Eq e/ou Hash você mesmo. Este guia não abordará os detalhes da implementação de Hash.

Para experimentar o uso de uma struct em um HashMap, vamos tentar criar um sistema de login de usuário muito simples:

use std::collections::HashMap;

// Eq requer que você derive PartialEq no tipo.
#[derive(PartialEq, Eq, Hash)]
struct Account<'a>{
    username: &'a str,
    password: &'a str,
}

struct AccountInfo<'a>{
    name: &'a str,
    email: &'a str,
}

type Accounts<'a> = HashMap<Account<'a>, AccountInfo<'a>>;

fn try_logon<'a>(accounts: &Accounts<'a>,
        username: &'a str, password: &'a str){
    println!("Username: {}", username);
    println!("Password: {}", password);
    println!("Tentando login...");

    let logon = Account {
        username,
        password,
    };

    match accounts.get(&logon) {
        Some(account_info) => {
            println!("Login bem-sucedido!");
            println!("Nome: {}", account_info.name);
            println!("Email: {}", account_info.email);
        },
        _ => println!("Login falhou!"),
    }
}

fn main(){
    let mut accounts: Accounts = HashMap::new();

    let account = Account {
        username: "j.everyman",
        password: "password123",
    };

    let account_info = AccountInfo {
        name: "John Everyman",
        email: "j.everyman@email.com",
    };

    accounts.insert(account, account_info);

    try_logon(&accounts, "j.everyman", "psasword123");

    try_logon(&accounts, "j.everyman", "password123");
}

Summary

Congratulations! You have completed the Alternate/Custom Key Types lab. You can practice more labs in LabEx to improve your skills.