从 if 语句分配一个未装箱的闭包
Assigning an unboxed closure from an if statement
我正在尝试更新 Rust 1 的代码。0.alpha,我遇到问题的部分可以简化为以下示例。我已经注释了闭合类型,并切换到未装箱的闭合。但是我找不到正确的乐趣类型。我试过 fun : FnMut() -> IoResult<u32>
但即使 FnMut、FnOnce 和朋友的全部意义在于提供闭包实现的特征;编译器似乎无法正确匹配类型。
我已阅读以下内容:
但是他们没有解释清楚如何处理这个问题
use std::io::File;
use std::io::IoResult;
use std::io::fs::PathExtensions;
use std::iter::range_step;
fn main() {
let path = Path::new("fid");
let mut file = File::open(&path);
let big = true;
let mut v = vec![];
let fun = if big {
|&mut:| file.read_be_u32()
} else {
|&mut:| file.read_le_u32()
};
for _ in range_step(0u64, path.stat().unwrap().size,4u64){
v.push(fun().unwrap());
}
println!("{}",v);
}
这给出:
scratch.rs:11:15: 15:6 error: if and else have incompatible types: expected `closure[scratch.rs:12:9: 12:35]`, found `closure[scratch.rs:14:9: 14:35]` (expected closure, found a different closure)
并使用 fun : FnMut() -> IoResult<u32>
或 fun : FnMut<(),IoResult<u32>>
得到:
scratch.rs:12:9: 12:35 error: mismatched types: expected `core::ops::FnMut() -> core::result::Result<u32, std::io::IoError>`, found `closure[scratch.rs:12:9: 12:35]` (expected trait core::ops::FnMut, found closure)
scratch.rs:12 |&mut:| file.read_be_u32()
^~~~~~~~~~~~~~~~~~~~~~~~~~
scratch.rs:14:9: 14:35 error: mismatched types: expected `core::ops::FnMut() -> core::result::Result<u32, std::io::IoError>`, found `closure[scratch.rs:14:9: 14:35]` (expected trait core::ops::FnMut, found closure)
scratch.rs:14 |&mut:| file.read_le_u32()
^~~~~~~~~~~~~~~~~~~~~~~~~~
以前,闭包会自动装箱,但现在我们有未装箱的闭包。从效率的角度来看,这是一件好事!
但是,在您的情况下,您希望有一个实现特征的绑定,但我们不关心变量的实际类型。在这种情况下,特征是 FnMut
,具体类型是自动生成的类型,对每个闭包都是唯一的。为此,我们需要有一个特征对象(如&Trait
或Box<Trait>
)。这是一个示例,我们重新装箱未装箱的闭包,创建特征对象:
use std::io::{File,IoResult};
use std::iter::range_step;
fn main() {
let path = Path::new("fid");
let mut file = File::open(&path);
let big = true;
let mut fun: Box<FnMut() -> IoResult<u32>> = if big {
Box::new(|&mut:| file.read_be_u32())
} else {
Box::new(|&mut:| file.read_le_u32())
};
println!("{:?}", fun())
}
这里是 没有 Box
:
use std::io::{File,IoResult};
use std::iter::range_step;
fn main() {
let path = Path::new("fid");
let mut file = File::open(&path);
let big = true;
let mut fun_be;
let mut fun_le;
let mut fun: &mut FnMut() -> IoResult<u32> = if big {
fun_be = |&mut:| file.read_be_u32();
&mut fun_be as &mut FnMut() -> _
} else {
fun_le = |&mut:| file.read_le_u32();
&mut fun_le as &mut FnMut() -> _
};
println!("{:?}", fun())
}
在处理预先存在的函数的地方,实际上根本不需要闭包;您可以直接使用函数,如下所示:
use std::io::{File,IoResult};
use std::iter::range_step;
fn main() {
let path = Path::new("fid");
let mut file = File::open(&path);
let big = true;
let fun: fn(_) -> _ = if big {
Reader::read_be_u32
} else {
Reader::read_le_u32
};
println!("{:?}", fun(&mut file))
}
(唉,: fn(_) -> _
是必须的。我不确定它是否会在某些时候变得不必要。)
我正在尝试更新 Rust 1 的代码。0.alpha,我遇到问题的部分可以简化为以下示例。我已经注释了闭合类型,并切换到未装箱的闭合。但是我找不到正确的乐趣类型。我试过 fun : FnMut() -> IoResult<u32>
但即使 FnMut、FnOnce 和朋友的全部意义在于提供闭包实现的特征;编译器似乎无法正确匹配类型。
我已阅读以下内容:
但是他们没有解释清楚如何处理这个问题
use std::io::File;
use std::io::IoResult;
use std::io::fs::PathExtensions;
use std::iter::range_step;
fn main() {
let path = Path::new("fid");
let mut file = File::open(&path);
let big = true;
let mut v = vec![];
let fun = if big {
|&mut:| file.read_be_u32()
} else {
|&mut:| file.read_le_u32()
};
for _ in range_step(0u64, path.stat().unwrap().size,4u64){
v.push(fun().unwrap());
}
println!("{}",v);
}
这给出:
scratch.rs:11:15: 15:6 error: if and else have incompatible types: expected `closure[scratch.rs:12:9: 12:35]`, found `closure[scratch.rs:14:9: 14:35]` (expected closure, found a different closure)
并使用 fun : FnMut() -> IoResult<u32>
或 fun : FnMut<(),IoResult<u32>>
得到:
scratch.rs:12:9: 12:35 error: mismatched types: expected `core::ops::FnMut() -> core::result::Result<u32, std::io::IoError>`, found `closure[scratch.rs:12:9: 12:35]` (expected trait core::ops::FnMut, found closure)
scratch.rs:12 |&mut:| file.read_be_u32()
^~~~~~~~~~~~~~~~~~~~~~~~~~
scratch.rs:14:9: 14:35 error: mismatched types: expected `core::ops::FnMut() -> core::result::Result<u32, std::io::IoError>`, found `closure[scratch.rs:14:9: 14:35]` (expected trait core::ops::FnMut, found closure)
scratch.rs:14 |&mut:| file.read_le_u32()
^~~~~~~~~~~~~~~~~~~~~~~~~~
以前,闭包会自动装箱,但现在我们有未装箱的闭包。从效率的角度来看,这是一件好事!
但是,在您的情况下,您希望有一个实现特征的绑定,但我们不关心变量的实际类型。在这种情况下,特征是 FnMut
,具体类型是自动生成的类型,对每个闭包都是唯一的。为此,我们需要有一个特征对象(如&Trait
或Box<Trait>
)。这是一个示例,我们重新装箱未装箱的闭包,创建特征对象:
use std::io::{File,IoResult};
use std::iter::range_step;
fn main() {
let path = Path::new("fid");
let mut file = File::open(&path);
let big = true;
let mut fun: Box<FnMut() -> IoResult<u32>> = if big {
Box::new(|&mut:| file.read_be_u32())
} else {
Box::new(|&mut:| file.read_le_u32())
};
println!("{:?}", fun())
}
这里是 Box
:
use std::io::{File,IoResult};
use std::iter::range_step;
fn main() {
let path = Path::new("fid");
let mut file = File::open(&path);
let big = true;
let mut fun_be;
let mut fun_le;
let mut fun: &mut FnMut() -> IoResult<u32> = if big {
fun_be = |&mut:| file.read_be_u32();
&mut fun_be as &mut FnMut() -> _
} else {
fun_le = |&mut:| file.read_le_u32();
&mut fun_le as &mut FnMut() -> _
};
println!("{:?}", fun())
}
在处理预先存在的函数的地方,实际上根本不需要闭包;您可以直接使用函数,如下所示:
use std::io::{File,IoResult};
use std::iter::range_step;
fn main() {
let path = Path::new("fid");
let mut file = File::open(&path);
let big = true;
let fun: fn(_) -> _ = if big {
Reader::read_be_u32
} else {
Reader::read_le_u32
};
println!("{:?}", fun(&mut file))
}
(唉,: fn(_) -> _
是必须的。我不确定它是否会在某些时候变得不必要。)