为什么对通用类型的迭代器过滤器中的比较操作不起作用?

时间:2018-07-07 12:10:12

标签: filter iterator rust

我试图理解为什么以下代码无法编译(Playground):

NpgsqlConnection connListenRun = new NpgsqlConnection("Server=tsimain;Port=5432;Database=racenetdb;UserId=postgres;Password=dragway42;SyncNotification=true;");
        try
        {
            connListenRun.Open();
            NpgsqlCommand cmd = new NpgsqlCommand("listen RunLogClient;", connListenRun);
            cmd.ExecuteNonQuery();
            connListenRun.Notification += new NotificationEventHandler(RunFinishNotification);
        }
        catch (NpgsqlException ex)
        {
            MessageBox.Show(ex.ToString());
        }
        finally
        {
            //connListen.Close();
        }
private void RunFinishNotification(object sender, NpgsqlNotificationEventArgs e)
    {
        GetData();
    }

错误是:

dataGridView1.DataSource = dt;

我尝试遵循here所述的各种替代方法(通过取消引用元素),但均未成功。

首次尝试:

fn inspection<I>(iter: I)
where 
    I: Iterator, 
    I::Item: Ord,
{
    let inspection = iter
        .filter(|x| x > 0);
}

fn main() {
    let data = vec![1, 2, 3];
    inspection(data.iter()); // or inspection(data.into_iter());
}
error[E0308]: mismatched types
 --> src/main.rs:9:25
  |
9 |         .filter(|x| x > 0);
  |                         ^ expected reference, found integral variable
  |
  = note: expected type `&<I as std::iter::Iterator>::Item`
             found type `{integer}`

第二次尝试:

.filter(|x| **x > 0); 
error[E0614]: type `<I as std::iter::Iterator>::Item` cannot be dereferenced
  --> src/main.rs:13:21
   |
13 |         .filter(|x| **x > 0);
   |  

为什么程序无法编译?

2 个答案:

答案 0 :(得分:3)

您真的快要解决第一个问题!您尝试过:

  • filter(|x| x > 0)
  • filter(|x| **x > 0)
  • filter(|&x| *x > 0)

解决方案是:filter(|x| *x > 0) filter(|&x| x > 0)

要了解原因,让我们再次仔细查看错误消息:

9 |         .filter(|x| x > 0);
  |                         ^ expected reference, found integral variable
  |
  = note: expected type `&<I as std::iter::Iterator>::Item`
             found type `{integer}`

它表示期望类型为&<I as std::iter::Iterator>::Item,并得到类型为{integer}。这意味着差异是一个参考。您无法将&i32i32进行比较。因此,您可以使用&(取消引用运算符)或*模式(也取消引用值)来删除一个|&x|。但是,如果将两者结合使用,则其效果与**相同:它将尝试两次取消引用。这是不可能的,因为该类型仅包含一个引用。


但是,由于更复杂的问题,它仍然无法编译。您可以在此处了解更多信息:

答案 1 :(得分:3)

最大的问题(另一个问题由Lukas解决)是您正在将迭代器的泛型项目与整数进行比较,而PartialOrd / Ord提供的比较仅在相同类型之间起作用:< / p>

pub trait Ord: Eq + PartialOrd<Self> {
    fn cmp(&self, other: &Self) -> Ordering;
    ...
}

为了使类型T与数字可比较(在这种情况下为0),T必须是数字,而0必须是类型T。包含有用数字特征的num条板箱可以在这里提供其https://github.com/kutyel/linq.ts特征,以提供通用的0

extern crate num;

use num::Zero;

fn inspection<'a, I, T: 'a>(iter: I)
where
    I: Iterator<Item = &'a T>,
    T: Zero + PartialOrd // T is an ordered number
{
    let inspection = iter.filter(|&x| *x > T::zero()); // T::zero() is 0 of the same type as T
}

fn main() {
    let data = vec![1, 2, 3];
    inspection(data.iter());
}