当依赖项的创建成本很高时该怎么办?
What to do when a dependency can be expensive to create?
我写了一个简单的程序来测试 Cloudflare 的 wirefilter,这是一个有效的例子。
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) -> Result<ExecutionContext, failure::Error> {
let mut ctx = ExecutionContext::new(Self::scheme());
ctx.set_field_value("port", self.port)?;
Ok(ctx)
}
}
fn main() -> Result<(), failure::Error> {
let data: Vec<MyStruct> = (0..10).map(|i| MyStruct { port: i as i32 }).collect();
let scheme = MyStruct::scheme();
let ast = scheme.parse("port in {2 5}")?;
let filter = ast.compile();
for i in data
.iter()
.filter(|d| filter.execute(&d.execution_context().unwrap()).unwrap())
{
println!("{:?}", i);
}
Ok(())
}
这将打印:
MyStruct { port: 2 }
MyStruct { port: 5 }
如果我创建向量data
在我验证模式之后,借用系统将开始抱怨。
我想在创建该向量之前验证用户输入 "port in {2 5}"
,这是一项昂贵的操作,有什么办法可以做到吗?
第二版代码为:
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) -> Result<ExecutionContext, failure::Error> {
let mut ctx = ExecutionContext::new(Self::scheme());
ctx.set_field_value("port", self.port)?;
Ok(ctx)
}
}
fn main() -> Result<(), failure::Error> {
let scheme = MyStruct::scheme();
let ast = scheme.parse("port in {2 5}")?;
let filter = ast.compile();
let data: Vec<MyStruct> = (0..10).map(|i| MyStruct { port: i as i32 }).collect();
for i in data.iter().filter(|d| filter.execute(&d.execution_context().unwrap()).unwrap()) {
println!("{:?}", i);
}
Ok(())
}
这将失败并显示此消息:
error[E0597]: `data` does not live long enough
--> src/main.rs:33:14
|
33 | for i in data.iter().filter(|d| filter.execute(&d.execution_context().unwrap()).unwrap()) {
| ^^^^ borrowed value does not live long enough
...
38 | }
| -
| |
| `data` dropped here while still borrowed
| borrow might be used here, when `filter` is dropped and runs the destructor for type `wirefilter::filter::Filter<'_>`
|
= note: values in a scope are dropped in the opposite order they are defined
我似乎可以在创建data
之前解析查询,但我无法编译它。
您可以将 data
的 声明 与其赋值分开:
let data: Vec<MyStruct>;
let scheme = MyStruct::scheme();
let ast = scheme.parse("port in {2 5}")?;
let filter = ast.compile();
data = (0..10).map(|i| MyStruct { port: i as i32 }).collect();
data
的生命周期与第一版代码相同,而赋值与第二版代码同时发生。
我写了一个简单的程序来测试 Cloudflare 的 wirefilter,这是一个有效的例子。
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) -> Result<ExecutionContext, failure::Error> {
let mut ctx = ExecutionContext::new(Self::scheme());
ctx.set_field_value("port", self.port)?;
Ok(ctx)
}
}
fn main() -> Result<(), failure::Error> {
let data: Vec<MyStruct> = (0..10).map(|i| MyStruct { port: i as i32 }).collect();
let scheme = MyStruct::scheme();
let ast = scheme.parse("port in {2 5}")?;
let filter = ast.compile();
for i in data
.iter()
.filter(|d| filter.execute(&d.execution_context().unwrap()).unwrap())
{
println!("{:?}", i);
}
Ok(())
}
这将打印:
MyStruct { port: 2 }
MyStruct { port: 5 }
如果我创建向量data
在我验证模式之后,借用系统将开始抱怨。
我想在创建该向量之前验证用户输入 "port in {2 5}"
,这是一项昂贵的操作,有什么办法可以做到吗?
第二版代码为:
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) -> Result<ExecutionContext, failure::Error> {
let mut ctx = ExecutionContext::new(Self::scheme());
ctx.set_field_value("port", self.port)?;
Ok(ctx)
}
}
fn main() -> Result<(), failure::Error> {
let scheme = MyStruct::scheme();
let ast = scheme.parse("port in {2 5}")?;
let filter = ast.compile();
let data: Vec<MyStruct> = (0..10).map(|i| MyStruct { port: i as i32 }).collect();
for i in data.iter().filter(|d| filter.execute(&d.execution_context().unwrap()).unwrap()) {
println!("{:?}", i);
}
Ok(())
}
这将失败并显示此消息:
error[E0597]: `data` does not live long enough
--> src/main.rs:33:14
|
33 | for i in data.iter().filter(|d| filter.execute(&d.execution_context().unwrap()).unwrap()) {
| ^^^^ borrowed value does not live long enough
...
38 | }
| -
| |
| `data` dropped here while still borrowed
| borrow might be used here, when `filter` is dropped and runs the destructor for type `wirefilter::filter::Filter<'_>`
|
= note: values in a scope are dropped in the opposite order they are defined
我似乎可以在创建data
之前解析查询,但我无法编译它。
您可以将 data
的 声明 与其赋值分开:
let data: Vec<MyStruct>;
let scheme = MyStruct::scheme();
let ast = scheme.parse("port in {2 5}")?;
let filter = ast.compile();
data = (0..10).map(|i| MyStruct { port: i as i32 }).collect();
data
的生命周期与第一版代码相同,而赋值与第二版代码同时发生。