Reputation: 23
To avoid nesting matches I am trying to use the and_then
method for Result
. The problem arises when I try to convert this
match Connection::open(&db_path) {
Ok(conn) => {
match conn.prepare("SELECT qwe,username_value,wer FROM my_table;") {
Ok(mut stmt) => {
match stmt.query_map([], |row| {Ok(row.get_unwrap::<usize, String>(1).clone())}) {
Ok(usernames) => {
for username in usernames {
if username.is_ok() {
println!("{}", username.expect("Could not read username value"));
}
}
println!("Query done");
},
Err(err) => println!("Error {}", err),
}
},
Err(err) => println!("Error {}", err),
}
},
Err(err) => println!("Error {}", err),
}
into this
match Connection::open(&db_path)
.and_then(move |conn: Connection| conn.prepare("SELECT qwe,username_value,wer FROM my_table;"))
.and_then(|mut stmt: Statement| stmt.query_map([], |row| {Ok(row.get_unwrap::<usize, String>(1).clone())})) {
Ok(usernames) => {
for username in usernames {
if username.is_ok() {
println!("{}", username.expect("Could not read username value"));
}
}
println!("Query done");
},
Err(_) => println!("Error querying db"),
}
The SQL lib is rusqlite.
The first snippet is accepted by the compiler, the second one is not. The compiler screams at me with the following error message:
error[E0515]: cannot return value referencing function parameter `conn`
--> src\main.rs:134:43
|
134 | .and_then(move |conn: Connection| conn.prepare("SELECT qwe,username_value,wer FROM my_table;"))
| ----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `conn` is borrowed here
error[E0515]: cannot return value referencing function parameter `stmt`
--> src\main.rs:135:41
|
135 | .and_then(|mut stmt: Statement| stmt.query_map([], |row| {Ok(row.get_unwrap::<usize, String>(1).clone())})) {
| ----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| returns a value referencing data owned by the current function
| `stmt` is borrowed here
error: aborting due to 2 previous errors
I tried with move
on the three closures but the error message is the same.
Why is the ownership wrong in the second snippet and which is the idiomatic way of writing something like this?
Upvotes: 0
Views: 126
Reputation: 23319
The problem is that conn.prepare
returns a statement that refers to conn
, but conn
is destroyed at the end of the closure so it's no longer here when the statement tries to use it. The idiomatic way to do what you want would be to use the ?
operator:
let conn = Connection::open(&db_path)?;
let mut stmt = conn.prepare("SELECT qwe,username_value,wer FROM my_table;")?;
for username in stmt.query_map([], |row| {Ok(row.get_unwrap::<usize, String>(1).clone())})? {
if username.is_ok() {
println!("{}", username.expect("Could not read username value"));
}
}
And let the caller handle the error. If you want to handle the error yourself, you can wrap the above code in a local function or closure (see also this question).
Upvotes: 1