2015-01-17 14 views
5

Cosa c'è di sbagliato con questo:Inversione di una stringa di Rust

fn main() { 
    let word: &str = "lowks"; 
    assert_eq!(word.chars().rev(), "skwol"); 
} 

ottengo un errore come questo:

error[E0369]: binary operation `==` cannot be applied to type `std::iter::Rev<std::str::Chars<'_>>` 
--> src/main.rs:4:5 
    | 
4 |  assert_eq!(word.chars().rev(), "skwol"); 
    |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    | 
    = note: an implementation of `std::cmp::PartialEq` might be missing for `std::iter::Rev<std::str::Chars<'_>>` 
    = note: this error originates in a macro outside of the current crate 

Qual è il modo corretto di fare questo?

risposta

12

Il primo, e più importante, problema è che questo non è il modo in cui si inverte una stringa Unicode. Stai invertendo l'ordine dei punti di codice, in cui si desidera invertire l'ordine di grafemi. Potrebbero esserci altri problemi con questo di cui non sono a conoscenza. Il testo è difficile

Il secondo problema è evidenziato dal compilatore: si sta tentando di confrontare una stringa letterale con un iteratore char. chars e rev non producono nuove stringhe, producono sequenze pigre, come con gli iteratori in generale. The following works:

/*! 
Add the following to your `Cargo.toml`: 

```cargo 
[dependencies] 
unicode-segmentation = "0.1.2" 
``` 
*/ 
extern crate unicode_segmentation; 
use unicode_segmentation::UnicodeSegmentation; 

fn main() { 
    let word: &str = "loẅks"; 
    let drow: String = word 
     // Split the string into an Iterator of &strs, where each element is an 
     // extended grapheme cluster. 
     .graphemes(true) 
     // Reverse the order of the grapheme iterator. 
     .rev() 
     // flat_map takes each element of an iterator, turns that element into 
     // a new iterator, then outputs the elements of these sub-iterators as 
     // one long chain. In this case, we're turning each grapheme cluster 
     // into an Iterator of code points, then yielding all those code points. 
     // That is, this is now an Iterator of chars from the reversed grapheme 
     // clusters. 
     .flat_map(|g| g.chars()) 
     // Collect all the chars into a new owned String. 
     .collect(); 

    assert_eq!(drow, "skẅol"); 

    // Print it out to be sure. 
    println!("drow = `{}`", drow); 
} 

Nota che graphemes usato per essere nella libreria standard come un metodo instabile, in modo che il sopra sarà rompere con sufficientemente vecchie versioni di Rust. In tal caso, è necessario utilizzare UnicodeSegmentation::graphemes(s, true).

+6

Penso che si può semplicemente '.rev() raccogliere()', in quanto ' String' implements 'FromIterator <&str>'. Inoltre, secondo me, il problema più reale * attuale * è fraintendere gli iteratori, gli archi e i tipi in generale (comprensibile, molte lingue non sono così "pedanti"), non i punti un po 'più sottili della correttezza dell'unicode. – huon

+0

@dbaupp: Direi che un problema indipendente dal linguaggio di implementazione è * più * fondamentale di uno specifico per una determinata lingua. : D Ma è bello sapere che 'String' supporta' FromIterator <&str> '. Peccato che non stia predisponendo lo storage, ma non puoi sempre ottenere quello che vuoi ... –

+0

Eh, la domanda riguarda il motivo per cui un determinato pezzo di codice non viene compilato in una particolare lingua, non perché sta dando un output inaspettato (cioè un problema indipendente dalla lingua con l'algoritmo), quindi il problema fondamentale per la domanda stessa è gli errori di tipo specifico di Ruggine. È sicuramente bene ricordare che l'unicode è difficile, però. – huon

10

Poiché, come @DK. suggerito, .graphemes() non è disponibile sul &str in stabile, si potrebbe anche solo fare quello che @huon suggerito nei commenti:.

fn main() { 
    let foo = "palimpsest"; 
    println!("{}", foo.chars().rev().collect::<String>()); 
} 
Problemi correlati