Types 从if语句分配未绑定的闭包

Types 从if语句分配未绑定的闭包,types,closures,rust,Types,Closures,Rust,我正在尝试更新Rust 1.0.alpha的代码,我遇到的一个问题可以简化为下面的示例。我已经注释了闭包类型,并切换到未绑定闭包。但是我找不到合适的娱乐类型。我尝试了fun:FnMut()->IoResult,但即使FnMut、FnOnce和friends的全部目的是提供闭包要实现的特性;编译器似乎无法正确匹配这些类型 我读过以下内容: 但他们没有明确解释如何处理这个问题 use std::io::File; use std::io::IoResult; use std::io::fs

我正在尝试更新Rust 1.0.alpha的代码,我遇到的一个问题可以简化为下面的示例。我已经注释了闭包类型,并切换到未绑定闭包。但是我找不到合适的娱乐类型。我尝试了
fun:FnMut()->IoResult
,但即使FnMut、FnOnce和friends的全部目的是提供闭包要实现的特性;编译器似乎无法正确匹配这些类型

我读过以下内容:

但他们没有明确解释如何处理这个问题

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
fun:FnMut
给出:

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()
                      ^~~~~~~~~~~~~~~~~~~~~~~~~~
scratch.rs:12:9:12:35错误:不匹配的类型:应为`core::ops::FnMut()->core::result::result`,找到`closure[scratch.rs:12:9:12:35]`(应为trait core::ops::FnMut,找到closure)
scratch.rs:12 |&mut:| file.read_be_u32()
^~~~~~~~~~~~~~~~~~~~~~~~~~
scratch.rs:14:9:14:35错误:不匹配的类型:应为`core::ops::FnMut()->core::result::result`,找到`closure[scratch.rs:14:9:14:35]`(应为trait core::ops::FnMut,找到closure)
scratch.rs:14 |&mut:| file.read_le_u32()
^~~~~~~~~~~~~~~~~~~~~~~~~~

以前,闭包会自动装箱,但现在我们有了未装箱的闭包。从效率的角度来看,这是一件好事

然而,在您的例子中,您希望有一个实现trait的绑定,但我们不关心变量的实际类型。在本例中,trait是
FnMut
,具体类型是自动生成的类型,每个闭包都是唯一的。为此,我们需要一个trait对象(如
&trait
)。下面是一个示例,我们重新装箱未装箱的闭包,创建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())
}
使用std::io::{File,IoResult};
使用std::iter::range\u步骤;
fn main(){
让路径=路径::新(“fid”);
让mut file=file::open(&path);
让大=真;
让mut有趣:Box IoResult>=如果很大{
Box::new(|&mut:| file.read_be_u32())
}否则{
Box::new(|&mut:| file.read_le_u32())
};
println!(“{:?}”,fun())
}

以前,闭包会自动装箱,但现在我们有了未装箱的闭包。从效率的角度来看,这是一件好事

然而,在您的例子中,您希望有一个实现trait的绑定,但我们不关心变量的实际类型。在本例中,trait是
FnMut
,具体类型是自动生成的类型,每个闭包都是唯一的。为此,我们需要一个trait对象(如
&trait
)。下面是一个示例,我们重新装箱未装箱的闭包,创建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())
}
使用std::io::{File,IoResult};
使用std::iter::range\u步骤;
fn main(){
让路径=路径::新(“fid”);
让mut file=file::open(&path);
让大=真;
让mut有趣:Box IoResult>=如果很大{
Box::new(|&mut:| file.read_be_u32())
}否则{
Box::new(|&mut:| file.read_le_u32())
};
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 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())
}
使用std::io::{File,IoResult};
使用std::iter::range\u步骤;
fn main(){
让路径=路径::新(“fid”);
让mut file=file::open(&path);
让大=真;
让我们一起快乐吧;
让我们一起玩吧;
让mut有趣:&mut FnMut()->IoResult=if big{
fun_be=|&mut:| file.read_be_u32();
&mut fun_be as&mut FnMut()->_
}否则{
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 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())
}
使用std::io::{File,IoResult};
使用std::iter::range\u步骤;
fn main(){
让路径=路径::新(“fid”);
让mut file=file::open(&path);
让大=真;
让我们一起快乐吧;
让我们一起玩吧;
让mut有趣:&mut FnMut()->IoResult=if big{
fun_be=|&mut:| file.read_be_u32();
&mut fun_be as&mut FnMut()->_
}否则{
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()->
是必要的。我不确定它在某个时候是否会变得不必要。)

在处理预先存在的函数时,实际上根本不需要闭包;您可以直接使用以下函数:

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()->
是必要的。我不确定它是否会在某个时候变得不必要。)

顺便说一句,为了简化样板文件,您可以只编写一次
Box IoResult>
let mut fun:Box IoResult>=…
,然后在
强制转换时省略
。理想情况下,这样的事情不需要装箱和堆分配。正如旧的闭包所证明的那样,基于堆栈的闭包已经足够了。但是,我找不到一种合适的方法来有条件地构造不同的基于
&mut
的trait对象:(@VladimirMatveev谢谢!我之前被一个编译器错误咬了一口。也许现在已经修复了!@VladimirMatveev我也在尝试同样的事情…
文件被多次借用。是的,如果它们是在分支中创建的,它们会很快被销毁…顺便说一句,为了减少模板,你可以编写
Box IoResult>
>只有一次:
让mut有趣:Box IoRsult>=…
,然后在
强制转换时省略
。理想情况下,这样的事情不需要装箱和堆分配。旧的闭包说明,基于堆栈的闭包已经足够了。但是,我找不到合适的方法有条件地构造不同的基于
&mut
的特征对象s:(@Vladimitmaveev th)