Generics 如何将某种通用闭包传递给函数以生成特定值

Generics 如何将某种通用闭包传递给函数以生成特定值,generics,closures,rust,Generics,Closures,Rust,这是我的第一个生锈项目。我正在开发一个基因编程API,我认为如果碱基对上的基因(在本例中是指令)可以被通用化(这是一个多表达式程序),那就太好了 这构建得很好,并且似乎可以工作,但是没有实现预期的用例。我希望用户能够访问PRNG的状态,该状态可以在多次调用新函数和其他函数时重用。就我而言,这是一个有问题的情况: ... extern crate rand; use rand::isaac::Isaac64Rng; use rand::SeedableRng; use rand::Rng; #[t

这是我的第一个生锈项目。我正在开发一个基因编程API,我认为如果碱基对上的基因(在本例中是指令)可以被通用化(这是一个多表达式程序),那就太好了

这构建得很好,并且似乎可以工作,但是没有实现预期的用例。我希望用户能够访问PRNG的状态,该状态可以在多次调用新函数和其他函数时重用。就我而言,这是一个有问题的情况:

...
extern crate rand;
use rand::isaac::Isaac64Rng;
use rand::SeedableRng;
use rand::Rng;
#[test]
fn mep_new() {
    let mut rng = Isaac64Rng::from_seed(&[1, 2, 3, 4]);
    let len = 80;
    let a: Mep<u32> = Mep::new(len, || rng.next_u32());
}
。。。
外部板条箱;
使用rand::isaac::Isaac64Rng;
使用rand::SeedableRng;
使用rand::Rng;
#[测试]
fn mep_new(){
设mut rng=Isaac64Rng::from_seed(&[1,2,3,4]);
设len=80;
设a:Mep=Mep::new(len,| | rng.next_u32());
}
我创建了一个新的PRNG,然后希望在闭包中捕获对它的可变引用。Rust抱怨此编译错误:

tests/mep.rs:12:40: 12:43 error: cannot borrow data mutably in a captured outer variable in an `Fn` closure [E0387]
tests/mep.rs:12     let a: Mep<u32> = Mep::new(len, || rng.next_u32());
                                                       ^~~
tests/mep.rs:12:40:12:43错误:无法可变地借用'Fn'闭包中捕获的外部变量中的数据[E0387]
tests/mep.rs:12让a:mep=mep::new(len,| | rng.next_u32());
^~~
我发现,这就意味着,该模型已被移动到这种新形式。所以我试着这样做:

#[test]
fn mep_new() {
    let mut rng = Isaac64Rng::from_seed(&[1, 2, 3, 4]);
    let len = 80;
    let a: Mep<u32> = Mep::new(len, |ref rng| rng.next_u32());
}
#[测试]
fn mep_new(){
设mut rng=Isaac64Rng::from_seed(&[1,2,3,4]);
设len=80;
设a:Mep=Mep::new(len,| ref rng | rng.next_u32());
}
但编译器抱怨:

tests/mep.rs:12:51: 12:61 error: the type of this value must be known in this context
tests/mep.rs:12     let a: Mep<u32> = Mep::new(len, |ref rng| rng.next_u32());
                                                                  ^~~~~~~~~~
tests/mep.rs:12:23: 12:31 error: type mismatch: the type `[closure@tests/mep.rs:12:37: 12:61]` implements the trait `core::ops::Fn<([type error],)>`, but the trait `core::ops::Fn<()>` is required (expected (), found tuple) [E0281]
tests/mep.rs:12     let a: Mep<u32> = Mep::new(len, |ref rng| rng.next_u32());
                                      ^~~~~~~~
tests/mep.rs:12:51:12:61错误:在此上下文中必须知道此值的类型
tests/mep.rs:12让a:mep=mep::new(len,| ref rng | rng.next_u32());
^~~~~~~~~~
测试/mep.rs:12:23:12:31错误:类型不匹配:类型不匹配`[closure@tests/mep.rs:12:37:12:61]`实现了trait`core::ops::Fn`,但trait`core::ops::Fn`是必需的(应为(),已找到元组)[E0281]
tests/mep.rs:12让a:mep=mep::new(len,| ref rng | rng.next_u32());
^~~~~~~~

我应该换一种方式吗?将迭代器传递给新函数是否更好?我不希望仅仅为了解决这个问题而将一个通用参数(在本例中是PRNG)从new传递到closure。解决这个问题的干净方法是什么?指令将以不同的格式出现,因此需要生成这样的指令。或者,我可以对特定的指令格式进行编码,但我希望看到这种通用方法能够发挥作用,这样我就可以利用Rust的功能,对多种指令格式使用相同的代码。

您需要做的主要更改是将通用绑定从
Fn
更改为
FnMut
。完成此操作后,还需要使参数
随机指令\u生成器
可变:

struct Mep<Ins> {
    instructions: Vec<Ins>,
}

impl<Ins> Mep<Ins> {
    fn new<F>(total_instructions: usize, mut random_instruction_generator: F) -> Mep<Ins>
        where F: FnMut() -> Ins
    {
        let instructions =
            (0..total_instructions)
            .map(|_| random_instruction_generator())
            .collect();

        Mep {
            instructions: instructions,
        }
    }
}

struct FakeRng;
impl FakeRng {
    // https://xkcd.com/221/
    fn next_u32(&mut self) -> u32 { 4 }
}

fn main() {
    let mut rng = FakeRng;
    let a = Mep::new(80, || rng.next_u32());
}
struct-Mep{
说明:Vec,
}
impl Mep{
fn新(总指令:usize,mut随机指令生成器:F)->Mep
其中F:FnMut()->Ins
{
让指示=
(0.指令总数)
.map(| |随机|指令_生成器())
.收集();
欧洲议会{
说明:说明,
}
}
}
结构FakeRng;
impl-FakeRng{
// https://xkcd.com/221/
fn next_u32(&mut self)->u32{4}
}
fn main(){
设mut rng=FakeRng;
设a=Mep::new(80,| | rng.next_u32());
}

我还将您的
where
子句更改为使用更标准的格式,并使用
map
collect
而不是可变向量。

请注意,您的两个链接都非常陈旧。Rust 1.0于2015年5月15日发布,1.0 betas之前发布的信息通常是可疑的。非常感谢。我仍然从C++中适应,因此也很高兴看到在RIST中如何使用迭代器。这是完全不同的,所以我从来没有想过返回欧洲议会那样!Rust中的复制消除潜力很强。我还将关注Rust中更多的标准格式实践。在这种情况下如何使用迭代器——我从具有良好迭代器的语言中学到的一点是,很少需要可变容器。此外,在许多情况下,您只需要一个
for
循环作为产生副作用的地方。更多的标准格式实践——最终,将是获得一致格式的简单解决方案^_^
tests/mep.rs:12:51: 12:61 error: the type of this value must be known in this context
tests/mep.rs:12     let a: Mep<u32> = Mep::new(len, |ref rng| rng.next_u32());
                                                                  ^~~~~~~~~~
tests/mep.rs:12:23: 12:31 error: type mismatch: the type `[closure@tests/mep.rs:12:37: 12:61]` implements the trait `core::ops::Fn<([type error],)>`, but the trait `core::ops::Fn<()>` is required (expected (), found tuple) [E0281]
tests/mep.rs:12     let a: Mep<u32> = Mep::new(len, |ref rng| rng.next_u32());
                                      ^~~~~~~~
struct Mep<Ins> {
    instructions: Vec<Ins>,
}

impl<Ins> Mep<Ins> {
    fn new<F>(total_instructions: usize, mut random_instruction_generator: F) -> Mep<Ins>
        where F: FnMut() -> Ins
    {
        let instructions =
            (0..total_instructions)
            .map(|_| random_instruction_generator())
            .collect();

        Mep {
            instructions: instructions,
        }
    }
}

struct FakeRng;
impl FakeRng {
    // https://xkcd.com/221/
    fn next_u32(&mut self) -> u32 { 4 }
}

fn main() {
    let mut rng = FakeRng;
    let a = Mep::new(80, || rng.next_u32());
}