2016-01-21 9 views
5

Quando si compila il seguente codice:Sottrazione non implementata per f32?

use std::io::*; 

fn main(){ 
    let reader = stdin(); 
    let nums = reader.lock() 
     .lines().next().unwrap().unwrap() 
     .split_whitespace() 
     .map(|s| s.parse::<i32>().unwrap()) 
     .map(|s| s as f32) 
     .map(|s| (s - 4)/2) 
     .map(|s| s as i32) 
     .collect(); 
} 

ottengo un errore che dice:

il tratto core::ops::Sub<_> non è implementata per il tipo di f32

Perché è questo?

risposta

10

La ruggine è più rigida di altri linguaggi quando si tratta di manipolare i tipi primitivi. La maggior parte degli operatori matematici richiede lo stesso tipo su entrambi i lati (ad eccezione dei bit shift, che si aspettano un usize come operando a destra). Ruggine non trasmetterà automaticamente i valori da un tipo numerico primitivo a un altro: è necessario inserire un cast esplicito nel codice. Questo codice dimostra la situazione:

fn main(){ 
    let a: i32 = 2; 
    let b: i8 = 3; 
    println!("{}", a + b); 
} 

Non riesce a compilare con i seguenti errori:

<anon>:4:24: 4:25 error: mismatched types: 
expected `i32`, 
    found `i8` 
(expected i32, 
    found i8) [E0308] 
<anon>:4  println!("{}", a + b); 
           ^
<std macros>:2:25: 2:56 note: in this expansion of format_args! 
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>) 
<anon>:4:5: 4:27 note: in this expansion of println! (defined in <std macros>) 
<anon>:4:24: 4:25 help: see the detailed explanation for E0308 
<anon>:4:20: 4:25 error: the trait `core::ops::Add<i8>` is not implemented for the type `i32` [E0277] 
<anon>:4  println!("{}", a + b); 
          ^~~~~ 
<std macros>:2:25: 2:56 note: in this expansion of format_args! 
<std macros>:3:1: 3:54 note: in this expansion of print! (defined in <std macros>) 
<anon>:4:5: 4:27 note: in this expansion of println! (defined in <std macros>) 
<anon>:4:20: 4:25 help: see the detailed explanation for E0277 

La vostra situazione è simile, ma ha la particolarità che si sta mescolando numeri interi e carri allegorici. In Rust, i valori letterali interi e float vengono assegnati a un tipo in base al contesto. È per questo motivo che è possibile impostare 2 ea su 210 sopra: 2 non è sempre un i32, ma è implicitamente digitato come i32 se il contesto lo richiede.

Nel tuo caso, stai cercando di sottrarre un numero intero da un f32. Il messaggio di errore menziona Sub<_>; che _ rappresenta il tipo di valore letterale 4 che il compilatore non era in grado di capire.

La soluzione è semplice da usare letterali pescante, invece letterali interi:

use std::io::*; 

fn main(){ 
    let reader = stdin(); 
    let nums = reader.lock() 
     .lines().next().unwrap().unwrap() 
     .split_whitespace() 
     .map(|s| s.parse::<i32>().unwrap()) 
     .map(|s| s as f32) 
     .map(|s| (s - 4.0)/2.0) 
     .map(|s| s as i32) 
     .collect::<Vec<_>>(); 
}