Can't figure out why this code won't compile
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!
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?
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 withUnot being copy or clonefn 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
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.
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
TandUneed to be'staticand if you add that bound when the macro expands theoutputvariable is a&mut Genso 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
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)
}
}