I have some code

struct DB { db : Connection } impl DB { // constructor fn new(file : &str) -> DB { let mut d = Connection::open(file).unwrap(); d.execute("create table if not exists u (i unsigned integer)", NO_PARAMS).unwrap(); DB {db : d} } // returns length of values fn len(&self) -> u32 { self.db.query_row("select count(i) from u", NO_PARAMS, |r| r.get(0)).unwrap() } fn print(&self) { if self.len() > 0 { let mut t = self.db.prepare("select i from u").unwrap(); for i in t.query_map(NO_PARAMS, |r| -> u32 { r.get(0) } ).unwrap() { println!("id {}", i.unwrap()); } } else { println!("Nothing"); } } } 

Is it possible for me to simplify something like this? What will it look like on the following code?

 struct DB { db : Connection } impl DB { // constructor fn new(file : &str) -> DB { let mut d = Connection::open(file).unwrap(); d.execute("create table if not exists u (i unsigned integer)", NO_PARAMS).unwrap(); DB {db : d} } // returns length of values fn len(&self) -> u32 { self.db.query_row("select count(i) from u", NO_PARAMS, |r| r.get(0)).unwrap() } fn iter(&self) -> MappedRows { self.db.prepare("select i from u").unwrap().query_map(NO_PARAMS, |r| -> u32 {r.get(0)} ).unwrap(); } fn print(&self) { if self.len() > 0 { for i in self.iter() { println!("id {}", i.unwrap()); } } else { println!("Nothing"); } } } 

But I have an error in place of MappedRows. He lacks some F, but as I rummaged, this is a lambda function or just a parameter that accepts a function. If you can’t simplify it until the second code, that's fine, and it’s desirable that you’d like to get some more elements from the base later. At once I will say that the database stores only a handful of numbers without id and all of this.

Error data

wrong number of type arguments: expected 1, found 0
expected 1 type argumentrustc (E0107)
main.rs (52, 27): expected 1 type argument
pub struct MappedRows <'stmt, F>
An iterator over the mapped result of a query.

I was also offered another option, but I only got more errors.

  fn iter<T, F>(&self) -> MappedRows<F> where F: FnMut(&Row<'_, '_>) -> T { let t = self.db.prepare("select i from u").unwrap(); t.query_map(NO_PARAMS, |r| -> u32 {r.get(0)} ).unwrap() } 

mismatched types

expected type parameter found closure

note: expected type rusqlite::MappedRows<'_, F>
found type rusqlite::MappedRows<'_, [closure@src/main.rs:56:36: 56:57]> rustc (E0308)
main.rs (56, 13): expected type parameter, found closure

    1 answer 1

    Created for you an example of how you can do: https://github.com/LooMaclin/return_mapped_rows_iter_example_rusqlite/blob/master/src/main.rs#L24-L34

    In short, the required signature for iter :

     fn iter<'a, 'stmt: 'a>(&'a self, stmt: &'a mut Statement<'stmt>) -> impl Iterator<Item = rusqlite::Result<u32>> + 'a { let query_map = stmt.query_map(NO_PARAMS, |r| -> u32 {r.get(0)}); let query_map_unwrapped = query_map.unwrap(); query_map_unwrapped } fn print(&self) { if self.len() > 0 { let mut stmt= self.db.prepare("select i from u").unwrap(); for i in self.iter(&mut stmt) { println!("id {}", i.unwrap()); } } else { println!("Nothing"); } } 

    Having seen the code, you will ask yourself why the creation of the Statement was made outside of the limits of the iter function. In order to explain this, I made a small example: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bef45646e58f71410af61deb142564f5

     struct A { a: String, } struct B<'a> { a: &'a str, } impl A { fn get_b(&self) -> B { B { a: &self.a } } } struct C; impl C { fn create_a(&self) -> A { A { a: "abc".to_string(), } } fn iter(&self) -> &B { let a = self.create_a(); &a.get_b() } } fn main() {} 

    In this case, the function created the Statement , which was dropped in its same skoupe. At the same time, the returned data ( MappedRows<'stmt> ) had a reference to the Statement . Here is the link:

    1) MappedRows<'stmt> keeps MappedRows<'stmt> in itself: https://docs.rs/rusqlite/0.16.0/src/rusqlite/row.rs.html#69-72

    2) Rows<'stmt> contains Option<&'stmt Statement<'stmt>> : https://docs.rs/rusqlite/0.16.0/src/rusqlite/row.rs.html#8-10

    Therefore, it becomes necessary to create a Statement , with such a lifetime, which is longer than the skopa of this function (that is, to receive it from the outside, in arguments).

    • Thank you, now I understand the whole essence of the problem. Where it's worth being closer ... - TerryChan Aleksandr