如何在无限数据流上使用 Wirefilter
How to use wirefilter over an infinite stream of data
我正在编写一个程序来使用 wirefilter 以从无限流中过滤数据。
但由于生命周期的原因,我似乎无法在循环中使用已编译的 ast,当我尝试编译时,这是输出:
error: borrowed data cannot be stored outside of its closure
--> src/main.rs:34:33
|
31 | let filter = ast.compile();
| ------ ...so that variable is valid at time of its declaration
32 |
33 | for my_struct in data.filter(|my_struct| {
| ----------- borrowed data cannot outlive this closure
34 | let execution_context = my_struct.execution_context();
| ^^^^^^^^^ ----------------- cannot infer an appropriate lifetime...
| |
| cannot be stored outside of its closure
error: aborting due to previous error
error: Could not compile `wirefilter_playground`.
To learn more, run the command again with --verbose.
main.rs
use wirefilter::{ExecutionContext, Scheme};
lazy_static::lazy_static! {
static ref SCHEME: Scheme = Scheme! {
port: Int
};
}
#[derive(Debug)]
struct MyStruct {
port: i32,
}
impl MyStruct {
fn scheme() -> &'static Scheme {
&SCHEME
}
fn execution_context(&self) -> ExecutionContext {
let mut ctx = ExecutionContext::new(Self::scheme());
ctx.set_field_value("port", self.port).unwrap();
ctx
}
}
fn main() -> Result<(), failure::Error> {
let data = expensive_data_iterator();
let scheme = MyStruct::scheme();
let ast = scheme.parse("port in {2 5}")?;
let filter = ast.compile();
for my_struct in data.filter(|my_struct| {
let execution_context = my_struct.execution_context();
filter.execute(&execution_context).unwrap()
}).take(10) {
println!("{:?}", my_struct);
}
Ok(())
}
fn expensive_data_iterator() -> impl Iterator<Item=MyStruct> {
(0..).map(|port| MyStruct { port })
}
Cargo.toml
[package]
name = "wirefilter_playground"
version = "0.1.0"
edition = "2018"
[dependencies]
wirefilter-engine = "0.6.1"
failure = "0.1.5"
lazy_static = "1.3.0"
有可能让它发挥作用吗?我只想为最终用户生成过滤后的数据,否则内存中的数据量会很大。
提前致谢!
看起来问题出在 return 结构中的生命周期省略。特别是这段代码:
fn execution_context(&self) -> ExecutionContext {
//...
}
相当于这个:
fn execution_context<'s>(&'s self) -> ExecutionContext<'s> {
//...
}
一旦您意识到 ExecutionContext
具有关联的生命周期,这一点就会变得显而易见。
ExecutionContext
的生命周期不必与 MyStruct
的生命周期相匹配,因此您可能想写:
fn execution_context<'e>(&self) -> ExecutionContext<'e> {
//...
}
或者也许:
fn execution_context<'s, 'e>(&'s self) -> ExecutionContext<'e>
where 'e: 's {
//...
}
取决于您的上下文最终是否会引用 MyStruct
的任何内容。
我正在编写一个程序来使用 wirefilter 以从无限流中过滤数据。
但由于生命周期的原因,我似乎无法在循环中使用已编译的 ast,当我尝试编译时,这是输出:
error: borrowed data cannot be stored outside of its closure
--> src/main.rs:34:33
|
31 | let filter = ast.compile();
| ------ ...so that variable is valid at time of its declaration
32 |
33 | for my_struct in data.filter(|my_struct| {
| ----------- borrowed data cannot outlive this closure
34 | let execution_context = my_struct.execution_context();
| ^^^^^^^^^ ----------------- cannot infer an appropriate lifetime...
| |
| cannot be stored outside of its closure
error: aborting due to previous error
error: Could not compile `wirefilter_playground`.
To learn more, run the command again with --verbose.
main.rs
use wirefilter::{ExecutionContext, Scheme};
lazy_static::lazy_static! {
static ref SCHEME: Scheme = Scheme! {
port: Int
};
}
#[derive(Debug)]
struct MyStruct {
port: i32,
}
impl MyStruct {
fn scheme() -> &'static Scheme {
&SCHEME
}
fn execution_context(&self) -> ExecutionContext {
let mut ctx = ExecutionContext::new(Self::scheme());
ctx.set_field_value("port", self.port).unwrap();
ctx
}
}
fn main() -> Result<(), failure::Error> {
let data = expensive_data_iterator();
let scheme = MyStruct::scheme();
let ast = scheme.parse("port in {2 5}")?;
let filter = ast.compile();
for my_struct in data.filter(|my_struct| {
let execution_context = my_struct.execution_context();
filter.execute(&execution_context).unwrap()
}).take(10) {
println!("{:?}", my_struct);
}
Ok(())
}
fn expensive_data_iterator() -> impl Iterator<Item=MyStruct> {
(0..).map(|port| MyStruct { port })
}
Cargo.toml
[package]
name = "wirefilter_playground"
version = "0.1.0"
edition = "2018"
[dependencies]
wirefilter-engine = "0.6.1"
failure = "0.1.5"
lazy_static = "1.3.0"
有可能让它发挥作用吗?我只想为最终用户生成过滤后的数据,否则内存中的数据量会很大。 提前致谢!
看起来问题出在 return 结构中的生命周期省略。特别是这段代码:
fn execution_context(&self) -> ExecutionContext {
//...
}
相当于这个:
fn execution_context<'s>(&'s self) -> ExecutionContext<'s> {
//...
}
一旦您意识到 ExecutionContext
具有关联的生命周期,这一点就会变得显而易见。
ExecutionContext
的生命周期不必与 MyStruct
的生命周期相匹配,因此您可能想写:
fn execution_context<'e>(&self) -> ExecutionContext<'e> {
//...
}
或者也许:
fn execution_context<'s, 'e>(&'s self) -> ExecutionContext<'e>
where 'e: 's {
//...
}
取决于您的上下文最终是否会引用 MyStruct
的任何内容。