Recursive async functions calling each other: cycle detected - asynchronous

The following code is the simplified version of the code I'm trying to write.
Coming from Go I'm finding it a bit difficult to deal with recursive functions calling each other.
First try (REPL on Playground here):
#[derive(Debug)]
struct Team {
id: String
}
impl Team {
pub async fn query(with_coach: bool) -> Result<Option<Team>, ()> {
if with_coach {
let coach = Coach::query(false).await?;
dbg!(coach);
}
Ok(None)
}
}
#[derive(Debug)]
struct Coach {
id: String
}
impl Coach {
pub async fn query(with_team: bool) -> Result<Option<Coach>, ()> {
if with_team {
let team = Team::query(false).await?;
dbg!(team);
}
Ok(None)
}
}
#[tokio::main]
async fn main() {
let team = Team::query(true).await;
dbg!(team);
}
the error is:
error[E0733]: recursion in an `async fn` requires boxing
--> src/main.rs:7:45
|
7 | pub async fn query(with_coach: bool) -> Result<Option<Team>, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
|
= note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
error[E0733]: recursion in an `async fn` requires boxing
--> src/main.rs:24:44
|
24 | pub async fn query(with_team: bool) -> Result<Option<Coach>, ()> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ recursive `async fn`
|
= note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
= note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
So I tried this second version (REPL on Playground here):
use std::{future::Future, pin::Pin};
#[derive(Debug)]
struct Team {
id: String,
}
impl Team {
pub async fn query<'a>(
id: &'a str,
with_coach: bool,
) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
Box::pin(async move {
if with_coach {
let coach = Coach::query("", false).await.await?;
dbg!(coach);
}
Ok(None)
})
}
}
#[derive(Debug)]
struct Coach {
id: String,
}
impl Coach {
pub async fn query<'a>(
id: &'a str,
with_team: bool,
) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
Box::pin(async move {
if with_team {
let team = Team::query("", false).await.await?;
dbg!(team);
}
Ok(None)
})
}
}
#[tokio::main]
async fn main() {
let team = Team::query("", true).await.await;
dbg!(team);
}
but as you can imagine there is a (very strange) error:
error[E0391]: cycle detected when computing type of `<impl at src/main.rs:8:1: 8:10>::query::{opaque#0}`
--> src/main.rs:12:10
|
12 | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires borrow-checking `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires processing `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires processing MIR for `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires unsafety-checking `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires building MIR for `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires building THIR for `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires type-checking `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:13:9
|
13 | / Box::pin(async move {
14 | | if with_coach {
15 | | let coach = Coach::query("", false).await.await?;
16 | |
... |
20 | | Ok(None)
21 | | })
| |__________^
= note: ...which requires evaluating trait selection obligation `for<'r, 's, 't0> {core::future::ResumeTy, bool, &'r str, impl for<'s> core::future::future::Future<Output = core::pin::Pin<alloc::boxed::Box<(dyn core::future::future::Future<Output = core::result::Result<core::option::Option<Coach>, ()>> + core::marker::Send + 's)>>>, (), core::pin::Pin<alloc::boxed::Box<(dyn core::future::future::Future<Output = core::result::Result<core::option::Option<Coach>, ()>> + core::marker::Send + 't0)>>}: core::marker::Send`...
note: ...which requires computing type of `<impl at src/main.rs:30:1: 30:11>::query::{opaque#0}`...
--> src/main.rs:34:10
|
34 | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires borrow-checking `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires processing `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires processing MIR for `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires unsafety-checking `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires building MIR for `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires building THIR for `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires type-checking `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:35:9
|
35 | / Box::pin(async move {
36 | | if with_team {
37 | | let team = Team::query("", false).await.await?;
38 | |
... |
42 | | Ok(None)
43 | | })
| |__________^
= note: ...which requires evaluating trait selection obligation `for<'r, 's, 't0> {core::future::ResumeTy, bool, &'r str, impl for<'s> core::future::future::Future<Output = core::pin::Pin<alloc::boxed::Box<(dyn core::future::future::Future<Output = core::result::Result<core::option::Option<Team>, ()>> + core::marker::Send + 's)>>>, (), core::pin::Pin<alloc::boxed::Box<(dyn core::future::future::Future<Output = core::result::Result<core::option::Option<Team>, ()>> + core::marker::Send + 't0)>>}: core::marker::Send`...
= note: ...which again requires computing type of `<impl at src/main.rs:8:1: 8:10>::query::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> src/main.rs:1:1
|
1 | / use std::{future::Future, pin::Pin};
2 | |
3 | | #[derive(Debug)]
4 | | struct Team {
... |
51 | | dbg!(team);
52 | | }
| |_^
error[E0391]: cycle detected when computing type of `<impl at src/main.rs:8:1: 8:10>::query::{opaque#0}`
--> src/main.rs:12:10
|
12 | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires borrow-checking `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires processing `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires processing MIR for `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires unsafety-checking `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires building MIR for `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires building THIR for `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:9:5
|
9 | / pub async fn query<'a>(
10 | | id: &'a str,
11 | | with_coach: bool,
12 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
| |____________________________________________________________________________^
note: ...which requires type-checking `<impl at src/main.rs:8:1: 8:10>::query`...
--> src/main.rs:13:9
|
13 | / Box::pin(async move {
14 | | if with_coach {
15 | | let coach = Coach::query("", false).await.await?;
16 | |
... |
20 | | Ok(None)
21 | | })
| |__________^
= note: ...which requires evaluating trait selection obligation `for<'r, 's, 't0> {core::future::ResumeTy, bool, &'r str, impl for<'s> core::future::future::Future<Output = core::pin::Pin<alloc::boxed::Box<(dyn core::future::future::Future<Output = core::result::Result<core::option::Option<Coach>, ()>> + core::marker::Send + 's)>>>, (), core::pin::Pin<alloc::boxed::Box<(dyn core::future::future::Future<Output = core::result::Result<core::option::Option<Coach>, ()>> + core::marker::Send + 't0)>>}: core::marker::Send`...
note: ...which requires computing type of `<impl at src/main.rs:30:1: 30:11>::query::{opaque#0}`...
--> src/main.rs:34:10
|
34 | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires borrow-checking `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires processing `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires processing MIR for `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires unsafety-checking `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires building MIR for `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires building THIR for `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
note: ...which requires type-checking `<impl at src/main.rs:30:1: 30:11>::query`...
--> src/main.rs:31:5
|
31 | / pub async fn query<'a>(
32 | | id: &'a str,
33 | | with_team: bool,
34 | | ) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
| |_____________________________________________________________________________^
= note: ...which again requires computing type of `<impl at src/main.rs:8:1: 8:10>::query::{opaque#0}`, completing the cycle
note: cycle used when checking item types in top-level module
--> src/main.rs:1:1
|
1 | / use std::{future::Future, pin::Pin};
2 | |
3 | | #[derive(Debug)]
4 | | struct Team {
... |
51 | | dbg!(team);
52 | | }
| |_^
What all this mean?
How can I fix this code?

You were very close. You just don't need async when you return boxed future. More details here and here
Async fn creates a state machine type containing each sub-Future being .awaited. For recursive async functions the resulting state machine type has to contain itself so you get infinitely-sized type. So you have to Box it.
However compiler restrictions won't allow just boxing at the moment. You have to make recursive function into a non-async function which returns a boxed async block.
This compiles and runs:
use std::{future::Future, pin::Pin};
#[derive(Debug)]
struct Team {
id: String,
}
impl Team {
pub fn query<'a>(
id: &'a str,
with_coach: bool,
) -> Pin<Box<dyn Future<Output = Result<Option<Team>, ()>> + Send + 'a>> {
Box::pin(async move {
if with_coach {
let coach = Coach::query("", false).await?;
dbg!(coach);
}
Ok(None)
})
}
}
#[derive(Debug)]
struct Coach {
id: String,
}
impl Coach {
pub fn query<'a>(
id: &'a str,
with_team: bool,
) -> Pin<Box<dyn Future<Output = Result<Option<Coach>, ()>> + Send + 'a>> {
Box::pin(async move {
if with_team {
let team = Team::query("", false).await?;
dbg!(team);
}
Ok(None)
})
}
}
#[tokio::main]
async fn main() {
let team = Team::query("", true).await;
dbg!(team);
}

Related

When using GADT in OCaml, how can I remove the 'less general definition' error message on a function?

I've been struggling with GADTs in OCaml recently. I'm trying to write an interpreter for a simple language, with different kinds of terms :
type (_, _) term =
| Const : lit -> (state, value) term
| Var : ident -> (state, value) term
| Plus : expr * expr -> (state, value) term
| Equ : expr * expr -> (state, value) term
| Neg : expr -> (state, value) term
| Skip : (state, state) term
| Asn : ident * expr -> (state, state) term
| Seq : stat * stat -> (state, state) term
| If : expr * stat * stat -> (state, state) term
| While : expr * stat -> (state, state) term
and expr = (state, value) term
and stat = (state, state) term
An ('a, 'b) term is a term that, when evaluated with an 'a, returns a 'b (typically, expressions are evaluated with a state and return a value, and statements are just modifying a given state into another one).
I've been trying to create functions for the interpreter, and I'm getting a weird error message that I cannot understand very well. This is the evaluating function :
let rec eval : type a b. a -> (a, b) term -> b = fun state term ->
match term with
| Const lit -> eval_lit_int state lit
| Var ident -> eval_var eval state ident
| Plus(e1, e2) -> eval_add eval state e1 e2
| Equ(e1, e2) -> eval_eq eval state e1 e2
| Neg e -> eval_neg eval state e
| Skip -> eval_skip eval state
| Asn(ident, e) -> eval_asn eval state ident e
| Seq(s1, s2) -> eval_seq eval state s1 s2
| If(e, s1, s2) -> eval_if eval state e s1 s2
| While(e, s) -> eval_while eval state e s
And here is an example of called function in the right-hand part of the pattern matching :
let eval_add f state e1 e2 =
let x1 = f state e1 in
let x1' =
match is_int x1 with
| None -> failwith ""
| Some x1' -> x1'
in
let x2 = f state e2 in
let x2' =
match is_int x2 with
| None -> failwith ""
| Some x2' -> x2'
in
match add x1' x2' with
| None -> failwith ""
| Some x0 -> x0
Don't mind the undocumented failures, the code is still being built at the moment. For the 'eval' function, I'm getting this error message and I cannot understand it :
This definition has type 'a -> ('a, 'b) term -> 'b
which is less general than 'a0 'b0. 'a0 -> ('a0, 'b0) term -> 'b0
Did someone have the same error message ? How can I make it disappear ? I guess it comes from the recursive call to 'eval', which I cannot really avoid. Thanks for your help !
First, let's add some hypotheses to circumvent the missing code:
Hypothesis 1:
You are using merlin. In this case, the error message
This definition has type 'a -> ('a, 'b) term -> 'b
which is less general than 'a0 'b0. 'a0 -> ('a0, 'b0) term -> 'b0
sometime happens to mask the real error message
Hypothesis 2:
Your eval_if and eval_while function look like
let eval_if eval state e s1 s2 =
if (to_bool ## eval state e) then
eval state s1
else
eval state s2
and
let eval_while eval st e s =
let st = ref st in
while (to_bool ## eval !st e) do
st := eval !st s
done; !st
Answer:
Then the true error lies in the fact that with these definitions both eval_while and eval_if returns a value and not a state. Indeed, the line to_bool ## eval !st e implies that the function argument eval must returns a value. Thus all subsequent call to eval state x returns a value since functions arguments are not polymorphic.
This can be fixed either by providing two evals functions, one for values and one for states to eval_while and eval_if or by wrapping the argument eval inside an record with a polymorphic field (which is OCaml way to emulate higher-rank polymorphism see http://caml.inria.fr/pub/docs/manual-ocaml/polymorphism.html#sec60):
type eval = { eval: 'a 'b. 'a -> ('a,'b) term -> 'b }
let eval_if {eval} state e s1 s2 =
if (to_bool ## eval state e) then
eval state s1
else
eval state s2
let eval_while {eval} st e s =
let st = ref st in
while (to_bool ## eval !st e) do
st := eval !st s
done; !st
then the following slightly amended eval function should work:
let rec eval : type a b. a -> (a, b) term -> b = fun state term ->
match term with
| Const lit -> eval_lit_int state lit
| Var ident -> eval_var eval state ident
| Plus(e1, e2) -> eval_add eval state e1 e2
| Equ(e1, e2) -> eval_eq eval state e1 e2
| Neg e -> eval_neg eval state e
| Skip -> eval_skip eval state
| Asn(ident, e) -> eval_asn eval state ident e
| Seq(s1, s2) -> eval_seq eval state s1 s2
| If(e, s1, s2) -> eval_if {eval} state e s1 s2
| While(e, s) -> eval_while {eval} state e s

How to do a subtraction between &ndarray::Array1<f64> and &mut Array1<f64>?

I find it impossible to do a subtraction between an immutable array reference and a mutable one using the ndarray crate:
#[macro_use]
extern crate ndarray;
use ndarray::Array1;
fn main() {
let a: &Array1<f64> = &array![3.0, 2.0, 1.0];
let b: &mut Array1<f64> = &mut array![1.0, 1.0, 1.0];
let c = a - &b.view(); // This compiles
let d = a - b; // This fails to compile
}
The error message I get is:
let d = a - b;
^ no implementation for `f64 - &mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
I don't understand what these two types mean, but is there any special reason why this is not implemented?
The Sub trait in ndarray::ArrayBase is not implemented for &mut arguments (it is for immutable references to other arrays). It is not needed because the right-handed value should not be modified. The second operand is a &mut Array<A, D>, and it ends up being one of the cases where type weakening into an immutable reference does not happen automatically. Still, you can explicitly reborrow the value:
let a: &Array1<f64> = &array![3.0, 2.0, 1.0];
let b: &mut Array1<f64> = &mut array![1.0, 1.0, 1.0];
let c = a - &b.view();
let d = a - &*b;
This assumes that a and b were obtained elsewhere. In fact, you can make these variables own the arrays instead:
let a: Array1<f64> = array![3.0, 2.0, 1.0];
let mut b: Array1<f64> = array![1.0, 1.0, 1.0];
let c = &a - &b.view();
let d = &a - &b;
The full error message is:
error[E0277]: the trait bound `f64: std::ops::Sub<&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>>` is not satisfied
--> src/main.rs:10:15
|
10 | let d = a - b;
| ^ no implementation for `f64 - &mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
|
= help: the trait `std::ops::Sub<&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>>` is not implemented for `f64`
= note: required because of the requirements on the impl of `std::ops::Sub<&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>>` for `&ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
error[E0277]: the trait bound `&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>: ndarray::ScalarOperand` is not satisfied
--> src/main.rs:10:15
|
10 | let d = a - b;
| ^ the trait `ndarray::ScalarOperand` is not implemented for `&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
|
= note: required because of the requirements on the impl of `std::ops::Sub<&mut ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>>` for `&ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
The first error message is quite obscure for me but the second is more enlightening:
the trait ndarray::ScalarOperand is not implemented for `&mut ndarray::ArrayBase
The reason of this error is that Rust does not perform coercions when matching traits: If there is an impl for some type U and T coerces to U, that does not constitute an implementation for T (copied directly from the Nomicon)
Without entering into ndarray internals, this is a minimal example reproducing the same problem:
trait MyShape {}
fn foo<T: MyShape>(x: T) -> T {
x
}
impl<'a> MyShape for &'a i32 {}
fn main() {
let mut num = 1;
let arg: &mut i32 = &mut num;
foo(arg);
}
Result:
error[E0277]: the trait bound `&mut i32: MyShape` is not satisfied
--> src/main.rs:12:5
|
12 | foo(arg);
| ^^^ the trait `MyShape` is not implemented for `&mut i32`
|
= help: the following implementations were found:
<&'a i32 as MyShape>
= note: required by `foo`

How can a vector of HashMaps be created and returned from main?

I would like to create a vector of HashMaps in Rust. I have tried the following:
fn main() -> Vec<HashMap<String, String>> {
let mut foo = HashMap::new();
foo.insert("".to_string(), "".to_string());
let f = Vec::new();
f.push(foo);
f
}
But I always get:
error[E0580]: main function has wrong type
--> src/main.rs:9:1
|
9 | / fn main() -> Vec<HashMap<String, String>> {
10 | | let mut foo = HashMap::new();
11 | | foo.insert("".to_string(), "".to_string());
12 | | let f = Vec::new();
13 | | f.push(foo);
14 | | f
15 | | }
| |_^ expected (), found struct `std::vec::Vec`
|
= note: expected type `fn()`
found type `fn() -> std::vec::Vec<std::collections::HashMap<std::string::String, std::string::String>>`
You try to return a value from fn main(), which isn't possible.
It will work if you rename your function and call it from main:
fn create_map() -> Vec<HashMap<String, String>> {
let mut foo = HashMap::new();
foo.insert("".to_string(), "".to_string());
let mut f = Vec::new();
f.push(foo);
f
}
fn main() {
create_map();
}
Playground
However, you also forgot to add mut to let f = Vec::new();
The compiler error has nothing to do with your vector or hashmap. It just states: "main function has wrong type". In Rust, every executable program starts at the function called main (located at the crate root). So that function name has a special meaning and a function called main at the crate root has to have a special signature (namely no arguments and () return type).
So you can fix the error by renaming your function and adding a mut. But you can write your code a bit more idiomatic with the vec![] macro:
fn get_vector() -> Vec<HashMap<String, String>> {
let mut foo = HashMap::new();
foo.insert("".to_string(), "".to_string());
vec![foo]
}
(Playground)

Why does iterating a vector of i32s give references to i32 (&i32)?

The following program tries to grade the marks of a student:
use std::io;
fn main() {
let mut in0 = String::new();
io::stdin().read_line(&mut in0).expect("stdin err");
let n: i32 = in0.trim().parse().expect("parse err");
println!("{}", n);
let mut v: Vec<i32> = Vec::new();
for _ in 0..n {
let mut inp = String::new();
io::stdin().read_line(&mut inp).expect("stdin err");
let num: i32 = inp.trim().parse().unwrap();
v.push(num);
}
let out: Vec<_> = v
.iter()
.map(|x| {
if x < 38 {
x
} else if x % 5 > 3 {
x + x % 5
} else {
x
}
})
.collect();
println!("{:?}", v);
}
While compiling, I get the following error.
error[E0308]: mismatched types
--> src/main.rs:19:20
|
19 | if x < 38 {
| ^^
| |
| expected `&i32`, found integer
| help: consider borrowing here: `&38`
error[E0308]: `if` and `else` have incompatible types
--> src/main.rs:24:17
|
21 | } else if x % 5 > 3 {
| ____________________-
22 | | x + x % 5
| | --------- expected because of this
23 | | } else {
24 | | x
| | ^ expected `i32`, found `&i32`
25 | | }
| |_____________- `if` and `else` have incompatible types
|
help: consider dereferencing the borrow
|
23 | } else *{
24 | x
25 | }
How is the x variable a &i32 type and not a i32 type?
Calling the .iter() method on a vector returns an iterator over references the vector's elements. Otherwise, it would have to move or copy the elements out of the vector, which is not desirable in the general case [1]. In the documentation this is not immediately obvious from the declaration:
pub fn iter(&self) -> Iter<T> // Return type does not look like a reference
However, the examples show that you get a reference:
assert_eq!(iterator.next(), Some(&1)); // note the `&1` instead of just `1`
The closure can be instructed to dereference the parameter:
v.iter().map(|&x| { /* do something */ })
This is fine if the vector contains Copyable types like i32. Otherwise this would result in a cannot move out of borrowed content error. In this case you will likely want to work with a reference anyway.
If you no longer need the vector after iterating you can use .into_iter(), which consumes the vector and iterates over owned items instead of references.
[1] Moving would clear the vector, which is covered by the .drain() method, and copying is not possible/efficient on all types.
If you want to consume the Vec, you must use into_iter() method:
use std::io;
fn main() {
let mut in0 = String::new();
io::stdin().read_line(&mut in0).expect("stdin err");
let n: i32 = in0.trim().parse().expect("parse err");
println!("{}", n);
let mut v: Vec<i32> = Vec::new();
for _ in 0 .. n {
let mut inp = String::new();
io::stdin().read_line(&mut inp).expect("stdin err");
let num: i32 = inp.trim().parse().unwrap();
v.push(num);
}
let out: Vec<_> = v.into_iter().map(|x| {
if x < 38 {
x
} else if x % 5 > 3 {
x + x % 5
} else {
x
}
}).collect();
println!("{:?}", out);
}
If you do not consume the vector, the things inside it can only be borrowed, not moved.

to disassemble a data type ocaml

In case I have to disassemble a data type as its variable size, can I still use the "match and with, and if the answer is yes you could help me figure out how (I'm a beginner with this language), or do I or use other methods.
the type defined is this :
type 'state formula =
| And of 'state formula list
| Or of 'state formula list
| Literal of bool
| Variable of 'state
from the examples I've seen the "match and with" is used when the structure of the static type was, in my case as I do?
So here's an example which uses match to work with your formula type:
type 'state formula = | And of 'state formula list | Or of 'state formula list | Literal of bool | Variable of 'state
let rec count_vars form = match form with
| And forms
| Or forms -> List.fold_left (+) 0 (List.map count_vars forms)
| Literal _ -> 0
| Variable _ -> 1
let formula = And [ Variable "q0"; Or[ Variable "q1";Variable "q2"]; Variable "q3"]
let vars_in_formula = count_vars formula (* 4 *)
If you want to manipulate the type, you can use patter matching(among other things, but I find this the most elegant). It's essentially syntactical sugar for Match with.
For example:
let identify_formula=function
And(l) -> 0
|Or(l) -> 1
|Literal(b) -> 2
| Variable(v) -> 3;;
For a less trivial example of how to manipulate types:
type l=Cons of int*l
| Nil;;
let rec sum_l=function
Cons(hd,tl)->hd+ sum_l(tl)
| Nil-> 0;;
sum_l(Cons(1,Cons(2,Cons(3,Nil))));; (*r6*)
Maybe you would like a code example to adapt to your needs.
type 'state formula =
| Literal of bool
| And of 'state formula list
| Or of 'state formula list
| Variable of 'state
let rec eval variable_env formula =
match formula with
| Literal b -> b
| Variable v -> variable_env v
| And formulas -> List.for_all (eval variable_env) formulas
| Or formulas -> List.exists (eval variable_env) formulas
(* same as eval, different code *)
let rec eval2 env = function
| Literal b -> b
| Variable v -> env v
| And [] -> true
| And (hd::tl) -> eval env hd && eval2 env (And tl)
| Or [] -> false
| Or (hd::tl) -> eval env hd || eval2 env (Or tl)

Resources