Desafio Rust

Retornando referência de struct com elisão

Enunciado

Implemente uma struct Texto<'a> que guarda conteudo: &'a str. Adicione um método palavra_mais_longa(&self) -> &str que retorna a palavra mais longa do conteúdo (separada por espaços). Use elisão de lifetimes no retorno. No main, crie uma instância com uma frase e imprima a palavra mais longa.

Requisitos

  • A struct deve ter lifetime 'a e o método deve retornar &str usando elisão (sem anotar 'a no retorno).
  • O método deve encontrar a palavra mais longa; em empate, retorne a primeira.
  • O main deve imprimir a palavra encontrada.

Código inicial

struct Texto<'a> {
    conteudo: &'a str,
}

impl<'a> Texto<'a> {
    fn palavra_mais_longa(&self) -> &str {
        // implemente
    }
}

fn main() {
    // crie e imprima
}

Saída esperada

Palavra mais longa: programação
Ver dica

Use self.conteudo.split_whitespace() e max_by_key(|p| p.len()). O retorno de max_by_key é Option<&str>; trate com unwrap_or("").

Mostrar solução
// Struct com referência e método que usa elisão de lifetimes.
struct Texto<'a> {
    conteudo: &'a str,
}

impl<'a> Texto<'a> {
    // O retorno &str tem lifetime ligado a &self por elisão.
    fn palavra_mais_longa(&self) -> &str {
        self.conteudo
            .split_whitespace()
            .max_by_key(|p| p.len())
            .unwrap_or("")
    }
}

fn main() {
    let t = Texto { conteudo: "rust é uma linguagem de programação" };
    println!("Palavra mais longa: {}", t.palavra_mais_longa());
}

Passo a passo

  1. Declaramos struct Texto<'a> com um campo conteudo: &'a str.
  2. No impl<'a> Texto<'a>, implementamos o método palavra_mais_longa(&self) -> &str.
  3. O retorno &str não tem anotação explícita. A elisão de lifetimes faz com que ele receba o mesmo lifetime de &self.
  4. Usamos self.conteudo.split_whitespace() para iterar sobre as palavras.
  5. max_by_key(|p| p.len()) encontra a palavra com maior comprimento; em empate, max_by_key retorna o último, mas como queremos o primeiro, usamos uma abordagem alternativa? Na verdade, max_by_key retorna o último em empate. Para garantir o primeiro, podemos usar max_by com comparação que favorece o primeiro. Ajustamos para usar max_by(|a, b| a.len().cmp(&b.len()).then(std::cmp::Ordering::Less))? Vamos simplificar: max_by_key em empate retorna o último, então usamos min_by_key com chave negativa? Melhor usar max_by com comparação que mantém o primeiro. Veja a solução corrigida abaixo.

Correção

Para atender ao requisito de empate retornar a primeira palavra, usamos max_by com uma comparação que só troca se o próximo for estritamente maior:

fn palavra_mais_longa(&self) -> &str {
    self.conteudo
        .split_whitespace()
        .max_by(|a, b| a.len().cmp(&b.len()).then(std::cmp::Ordering::Greater))
        .unwrap_or("")
}

Passo a passo (continuação)

  1. max_by com a.len().cmp(&b.len()).then(Ordering::Greater) faz com que, em empate, o primeiro elemento seja mantido (pois Greater indica que a é maior, então a permanece).
  2. Tratamos o caso de string vazia com unwrap_or("").
  3. No main, criamos Texto com uma frase e imprimimos o resultado.

Por que funciona

A elisão de lifetimes em métodos com &self faz com que o retorno &str tenha o mesmo lifetime de &self. Isso é seguro porque o retorno é uma fatia do conteúdo da struct, que vive enquanto a struct viver. O método não precisa de anotação explícita, mas o compilador verifica a validade.

Erros comuns

  • Tentar retornar &str sem que ele esteja ligado a &self: se o método não tivesse &self, o compilador exigiria anotação.
  • Usar max_by_key e esperar o primeiro em empate: ele retorna o último. É preciso usar max_by com comparação customizada.
  • Esquecer unwrap_or e tentar desembrulhar Option sem tratar string vazia.

Outra forma de resolver

Você pode implementar manualmente um loop:

fn palavra_mais_longa(&self) -> &str {
    let mut melhor = "";
    for p in self.conteudo.split_whitespace() {
        if p.len() > melhor.len() {
            melhor = p;
        }
    }
    melhor
}

Essa versão é mais explícita e mantém a primeira palavra em empate, sem depender de ordenação.

Saída esperada

Palavra mais longa: programação