2016-08-08 3 views
0

У меня есть этот небольшой фрагмент, но он не компилируется и все ошибки связаны с тем, что combinations_n возвращает &Vec<&u8> вместо &Vec<u8>.Ожидаемый тип `& Vec <u8>`, `найдено & Vec <&u8>`

extern crate itertools; 

use std::io; 
use std::collections::BTreeMap; 
use std::iter::Enumerate; 
use itertools::Itertools; 

const RANKS: [u8; 13] = [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]; 

fn is_straight(hand: &Vec<u8>) -> bool { 
    for (i, h) in hand[1..].iter().enumerate() { 
     if h - hand[i] != 1 { 
      return false; 
     } 
    } 
    true 
} 

fn hand_value(hand: &Vec<u8>) -> u8 { 
    hand.iter().fold(0_u8, |a, &b| a + 2u8.pow(b as u32)); 
} 

fn generate_flush_table() -> BTreeMap<u8,u8> { 
    let ft = BTreeMap::new(); 
    let mut straight_counter = 1; 
    let mut other_counter = 323; 
    for flush in RANKS.iter().combinations_n(5) { 
     if flush == [12, 3, 2, 1, 0] { 
      continue; 
     } else if is_straight(&flush) { 
      ft.insert(hand_value(&flush), straight_counter); 
      straight_counter += 1; 
     } else { 
      ft.insert(hand_value(&flush), other_counter); 
      other_counter += 1; 
     } 
    } 
    ft 
} 


fn main() { 
    let flush_table: BTreeMap<u8,u8> = generate_flush_table(); 
    for (key, value) in flush_table.iter() { 
     println!("{}: {}", key, value); 
    } 
} 

Вот что говорит составитель:

error: the trait bound `&u8: std::cmp::PartialEq<_>` is not satisfied [E0277] 
     if flush == [12, 3, 2, 1, 0] { 
      ^~~~~~~~~~~~~~~~~~~~~~~~~ 
help: run `rustc --explain E0277` to see a detailed explanation 
help: the following implementations were found: 
help: <u8 as std::cmp::PartialEq> 
note: required because of the requirements on the impl of `std::cmp::PartialEq<[_; 5]>` for `std::vec::Vec<&u8>` 
error: mismatched types [E0308] 
     } else if is_straight(&flush) { 
           ^~~~~~ 
help: run `rustc --explain E0308` to see a detailed explanation 
note: expected type `&std::vec::Vec<u8>` 
note: found type `&std::vec::Vec<&u8>` 
error: mismatched types [E0308] 
      ft.insert(hand_value(&flush), straight_counter); 
           ^~~~~~ 
help: run `rustc --explain E0308` to see a detailed explanation 
note: expected type `&std::vec::Vec<u8>` 
note: found type `&std::vec::Vec<&u8>` 
error: mismatched types [E0308] 
      ft.insert(hand_value(&flush), other_counter); 
           ^~~~~~ 
help: run `rustc --explain E0308` to see a detailed explanation 
note: expected type `&std::vec::Vec<u8>` 
note: found type `&std::vec::Vec<&u8>` 

Я действительно не понимаю, как тип flush может быть действительно &Vec<&u8>, учитывая, что combinations_n возвращает CombinationsN и в документации, которую я прочитал

impl<I> Iterator for CombinationsN<I> 
    where I: Iterator, 
      I::Item: Clone 
{ 
    type Item = Vec<I::Item> 

и поэтому на самом деле это должно быть Vec<u8>.

ответ

3

Как профессиональный программист, вы должны научиться создавать Minimal, Complete, and Verifiable example. Вот один для вашей проблемы:

extern crate itertools; 
use itertools::Itertools; 

const RANKS: [u8; 13] = [12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]; 

fn main() { 
    let one_combination:() = RANKS.iter().combinations_n(5).next(); 
} 

Какой сбой с соответствующей ошибкой:

error: mismatched types [E0308] 
    let one_combination:() = RANKS.iter().combinations_n(5).next(); 
           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
help: run `rustc --explain E0308` to see a detailed explanation 
note: expected type `()` 
note: found type `std::option::Option<std::vec::Vec<&u8>>` 

Это показывает, что это частности вызов combinations_n действительно производят Vec<&u8>, не Vec<u8>.

Так почему это?

Эта строка из определения CombinationsN является ключевым:

type Item = Vec<I::Item> 

CombinationsN является итератора адаптер, так I::Item тип итератора, который предшествует ему. В нашем случае, что это? slice::Iter, который имеет это:

type Item = &'a T 

Так итерируя над ломтиком, вы получите ссылки на элементы среза, а затем ссылка самой передается CombinationsN, который затем клоны ссылки и собирающей это в Vec.

Одним из решений является клонировать итерированные элементы:

RANKS.iter().cloned().combinations_n(5) 
+0

Спасибо. Я фактически удалил довольно много кода, и я подумал, что это был достаточно маленький пример. Я буду более внимателен в будущем. Также спасибо за подробное объяснение. – rubik

+0

@рубик не беспокоится! Я просто склонен указывать на более мелкие версии, которые могут быть созданы, потому что обычно есть несколько шагов по уменьшению примера. По крайней мере, ваш вопрос включал достаточно информации, чтобы реально воспроизвести проблему!^_ ^ – Shepmaster

Смежные вопросы