我在学生锈(来自haskell的背景)。我很难使用多态类型--在haskell中,我会使用类型孔/GHC的类型推断来确定函数的返回类型是什么--我陷在铁锈中,专门处理一个泛型参数。
我目前的问题
假设我有一种类型描述了一个柚子会话(我将这些数据存储在一个sqllite数据库中),并且我想在一个推桌中显示这些数据。
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是一个具有以下定义的枚举:
pub enum Row<D, I> where
D: Iterator<Item = I>,
I: Display, {
Data(D),
StyledData(D, Style),
}我尝试将不正确的类型插入到专门的类型签名中
pub fn as_row(self) -> Row<?,?> {也就是说,再次用?替换i32,编译器告诉我i32不是迭代器,但是我不知道如何进一步专门化。
为完整性着想
为了在这里更容易地进行调查:https://github.com/epsilonhalbe/pomodorust/tree/4f8c4929201ed90ddaef8af8d21076dbde78782b是一个可以克隆和构建的github项目的链接。我在这里发布的错误可以通过移动src/database.rs复制,从而使编译失败。
奖励:
如果haskell中有类似于_的内容,可以告诉我锈蚀编译器正在推断什么类型,那么我就可以从文档中挑选出示例。
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);发布于 2019-12-30 05:53:49
@kopecs是对的。Row<std::slice::Iter<'a, String>, &'a String>将是正确的返回类型,但正如他们解释的那样,它将导致生存期问题,因为它将返回对局部变量的引用。
tui::widgets::Row要求其类型D为Iterator。在数组上使用数组和into_iter的问题是,IntoIterator只是为&[T;N]和&mut [T;N]实现的,即引用。这最好由这个Reddit线程来解释
任何这样的实现都需要将元素从数组中移出,这会在数组中留下漏洞,如果在迭代过程中出现恐慌,会导致糟糕的事情发生 ..。 我相信,在恐慌的情况下,Vec通过泄漏记忆来解决这个问题。
无论如何,解决这个问题的一种方法是只使用Vec而不是数组。然后,迭代器可以拥有字符串,而不是只保存对原始数组中字符串的引用。固定方法如下:
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())
}https://stackoverflow.com/questions/59524738
复制相似问题