首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多态类型的专门化类型

多态类型的专门化类型
EN

Stack Overflow用户
提问于 2019-12-30 01:19:55
回答 1查看 91关注 0票数 3

我在学生锈(来自haskell的背景)。我很难使用多态类型--在haskell中,我会使用类型孔/GHC的类型推断来确定函数的返回类型是什么--我陷在铁锈中,专门处理一个泛型参数。

  • 锈蚀: 1.39.0
  • 货物: 1.39.0
  • tui-图书馆: 0.8.0
  • 操作系统: linux薄荷

我目前的问题

假设我有一种类型描述了一个柚子会话(我将这些数据存储在一个sqllite数据库中),并且我想在一个推桌中显示这些数据。

代码语言:javascript
复制
use tui::widgets::Row;

pub struct Pom {
    pub id: i32,
    pub duration: i64,
    pub ticket_id: Option<String>,
    pub note: Option<String>,
}

impl Pom {
    pub fn as_row(self) -> ? {
        let ret : [String; 4] = [
            format!("{}", self.id),
            format!("{}", self.duration),
            self.ticket_id.unwrap_or(String::new()),
            self.note.unwrap_or(String::new()),
        ];
        Row::Data(ret.into_iter())
    }
}

编译器非常有用,当我用?代替i32 (如(如何在Rust中打印变量的类型?)中的建议)时,它告诉我它需要某种类型的Row

我知道Row是一个具有以下定义的枚举:

代码语言:javascript
复制
pub enum Row<D, I> where
    D: Iterator<Item = I>,
    I: Display,  {
    Data(D),
    StyledData(D, Style),
}

我尝试将不正确的类型插入到专门的类型签名中

代码语言:javascript
复制
pub fn as_row(self) -> Row<?,?> {

也就是说,再次用?替换i32,编译器告诉我i32不是迭代器,但是我不知道如何进一步专门化。

为完整性着想

为了在这里更容易地进行调查:https://github.com/epsilonhalbe/pomodorust/tree/4f8c4929201ed90ddaef8af8d21076dbde78782b是一个可以克隆和构建的github项目的链接。我在这里发布的错误可以通过移动src/database.rs复制,从而使编译失败。

奖励:

如果haskell中有类似于_的内容,可以告诉我锈蚀编译器正在推断什么类型,那么我就可以从文档中挑选出示例。

代码语言:javascript
复制
let row_style = Style::default().fg(Color::White);
Table::new(
        ["Col1", "Col2", "Col3"].into_iter(),
        vec![
            Row::StyledData(["Row11", "Row12", "Row13"].into_iter(), row_style),
            Row::StyledData(["Row21", "Row22", "Row23"].into_iter(), row_style),
            Row::StyledData(["Row31", "Row32", "Row33"].into_iter(), row_style),
            Row::Data(["Row41", "Row42", "Row43"].into_iter())
        ].into_iter()
    )
    .block(Block::default().title("Table"))
    .header_style(Style::default().fg(Color::Yellow))
    .widths(&[Constraint::Length(5), Constraint::Length(5), Constraint::Length(10)])
    .style(Style::default().fg(Color::White))
    .column_spacing(1);
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-12-30 05:53:49

@kopecs是对的。Row<std::slice::Iter<'a, String>, &'a String>将是正确的返回类型,但正如他们解释的那样,它将导致生存期问题,因为它将返回对局部变量的引用。

tui::widgets::Row要求其类型DIterator。在数组上使用数组和into_iter的问题是,IntoIterator只是为&[T;N]和&mut [T;N]实现的,即引用。这最好由这个Reddit线程来解释

任何这样的实现都需要将元素从数组中移出,这会在数组中留下漏洞,如果在迭代过程中出现恐慌,会导致糟糕的事情发生 ..。 我相信,在恐慌的情况下,Vec通过泄漏记忆来解决这个问题。

无论如何,解决这个问题的一种方法是只使用Vec而不是数组。然后,迭代器可以拥有字符串,而不是只保存对原始数组中字符串的引用。固定方法如下:

代码语言:javascript
复制
pub fn as_row(self) -> Row<impl Iterator<Item=String>, String> {  // <-- correct return type
    let ret = vec![  // <-- use a Vec
        format!("{}", self.id),
        format!("{}", self.duration),
        self.ticket_id.unwrap_or(String::new()),
        self.note.unwrap_or(String::new()),
    ];
    Row::Data(ret.into_iter())
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59524738

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档