期望的类型`&amp; Vec <u8>`,找到`&amp; Vec&lt;&amp; u8&gt;`

时间:2016-08-08 19:14:25

标签: types rust

我有这个小片段,但它没有编译,所有错误都源于combinations_n返回&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返回CombinationsN并在我阅读的文档中,我真的不明白&Vec<&u8>的类型如何combinations_n / p>

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

所以它实际上应该是Vec<u8>

1 个答案:

答案 0 :(得分:4)

作为一名专业程序员,您应该学会制作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)