genawaiter icon indicating copy to clipboard operation
genawaiter copied to clipboard

Can't figure out why this code won't compile

Open Keithcat1 opened this issue 4 years ago • 5 comments

I have the following bit of code and it won't compile: use {serde::{de::DeserializeOwned}, std::io::Read, genawaiter::{yield_, stack::let_gen}};

fn stream_iter<T: DeserializeOwned, U: Read>(reader: U) -> impl Iterator<Item=serde_json::Result<T>> { let_gen!(output, { loop { yield_!(serde_json::from_reader<U, T>(reader)); } }); return output.into_iter(); } fn main() { } The generator is supposed to read values of type T from an std::io::Read by using serde_json to deserialize the data. The error I am getting is this: error: no rules expected the token @ --> src\bin\stdin_json.rs:4:2 | 4 | / let_gen!(output, { 5 | | loop { 6 | | yield_!(serde_json::from_reader<U, T>(reader)); 7 | | } 8 | | }); | |_______^ no rules expected this token in macro call | = note: this error originates in a macro (in Nightly builds, run with -Z macro -backtrace for more info)

error: aborting due to previous error

Thanks for the library BTW. Generators are cool!

Keithcat1 avatar Jun 16 '21 20:06 Keithcat1

I think you just need a turbofish on serde_json::from_reader::<U, T>(reader) but you will run into other problems with U not being copy or clone

fn stream_iter<T: DeserializeOwned, U: Read + Clone>(reader: U) -> Vec<serde_json::Result<T>> {
    let_gen!(output, {
        loop {
            yield_!(serde_json::from_reader::<U, T>(reader.clone()));
        }
    });
    output.into_iter().collect()
}
fn main() {}

This works but may not be what you need?

DevinR528 avatar Jun 17 '21 10:06 DevinR528

Thanks, but why is it returning a Vec<T> instead of the generator as an iterator? This is a toy example so I could play with generators. I was going to use it to read JSON from stdin, and your approach would never return anything.

On 6/17/21, Devin Ragotzy @.***> wrote:

I think you just need a turbofish on serde_json::from_reader::<U, T>(reader) but you will run into other problems with U not being copy or clone

fn stream_iter<T: DeserializeOwned, U: Read + Clone>(reader: U) ->
Vec<serde_json::Result<T>> {
    let_gen!(output, {
        loop {
            yield_!(serde_json::from_reader::<U, T>(reader.clone()));
        }
    });
    output.into_iter().collect()
}
fn main() {}

This works but may not be what you need?

-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/whatisaphone/genawaiter/issues/31#issuecomment-863139901

Keithcat1 avatar Jun 17 '21 18:06 Keithcat1

Lifetime issues because T and U need to be 'static and if you add that bound when the macro expands the output variable is a &mut Gen so the function can't return a reference owned by the function.

Here is the expanded output

fn gener() {
    use std::io::Read;
    use genawaiter::{stack::let_gen, yield_};
    use serde::de::DeserializeOwned;
    fn stream_iter<T: DeserializeOwned + 'static, U: Read + Clone + 'static>(
        reader: U,
    ) -> Vec<serde_json::Result<T>> {
        let mut shelf = ::genawaiter::stack::Shelf::new();
        let mut generator = unsafe {
            ::genawaiter::stack::Gen::new(&mut shelf, {
                #[allow(dead_code)]
                enum ProcMacroHack {
                    Value = ( "{ loop  { yield_!(serde_json :: from_reader :: < U, T > (reader.clone())); } }" , 0 ) . 1 , }
                |__private_co_arg__: ::genawaiter::stack::Co<'_, _, _>| async move {
                    loop {
                        __private_co_arg__
                            .yield_(serde_json::from_reader::<U, T>(reader.clone()))
                            .await;
                    }
                }
            })
        };
        let output = &mut generator;
        output.into_iter().collect()
    }
    fn main() {}
}

You could pass in a callback or something like that since your right collecting into a Vec kinda defeats the purpose.

DevinR528 avatar Jun 17 '21 20:06 DevinR528

Shouldn't it be possible to somehow return generators from functions? Returning iterators from functions seems like a common use case which would allow other crates to return generators that are actually iterators instead of having to write their own iterators.

On 6/17/21, Devin Ragotzy @.***> wrote:

Lifetime issues because T and U need to be 'static and if you add that bound when the macro expands the output variable is a &mut Gen so the function can't return a reference owned by the function.

Here is the expanded output

fn gener() {
    use std::io::Read;
    use genawaiter::{stack::let_gen, yield_};
    use serde::de::DeserializeOwned;
    fn stream_iter<T: DeserializeOwned + 'static, U: Read + Clone +
'static>(
        reader: U,
    ) -> Vec<serde_json::Result<T>> {
        let mut shelf = ::genawaiter::stack::Shelf::new();
        let mut generator = unsafe {
            ::genawaiter::stack::Gen::new(&mut shelf, {
                #[allow(dead_code)]
                enum ProcMacroHack {
                    Value = ( "{ loop  { yield_!(serde_json :: from_reader
:: < U, T > (reader.clone())); } }" , 0 ) . 1 , }
                |__private_co_arg__: ::genawaiter::stack::Co<'_, _, _>|
async move {
                    loop {
                        __private_co_arg__
                            .yield_(serde_json::from_reader::<U,
T>(reader.clone()))
                            .await;
                    }
                }
            })
        };
        let output = &mut generator;
        output.into_iter().collect()
    }
    fn main() {}
}

You could pass in a callback or something like that since your right collecting into a Vec kinda defeats the purpose.

-- You are receiving this because you authored the thread. Reply to this email directly or view it on GitHub: https://github.com/whatisaphone/genawaiter/issues/31#issuecomment-863532125

Keithcat1 avatar Jun 17 '21 20:06 Keithcat1

Well this works but you can't have T because of type limitations

fn sterff() {
    use std::io::Read;

    use genawaiter::{rc::gen, yield_};
    use serde::de::DeserializeOwned;

    fn stream_iter<U: Read>(
        mut reader: impl Iterator<Item = U>,
    ) -> impl Iterator<Item = serde_json::Result<serde_json::Value>> {
        gen!({
            loop {
                yield_!(serde_json::from_reader::<U, serde_json::Value>(
                    reader.next().unwrap()
                ))
            }
        })
        .into_iter()
    }

    let reader: Vec<&[u8]> = vec![b"{}", b"\"string\"", b"123"];
    for x in stream_iter(reader.into_iter()) {
        println!("{:?}", x)
    }
}

DevinR528 avatar Jun 18 '21 19:06 DevinR528