gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 08:08:02 25 4
gpt4 key购买 nike

这是我的第一个 Rust 项目。我正在研究一个遗传编程 API,我认为如果碱基对上的基因(在本例中是指令)可以通用(这是一个多表达程序),那会很好。

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

我尝试创建一个新函数,该函数采用闭包在向量中生成 Ins:

impl<Ins> Mep<Ins> {
//Generates a new Mep with a particular size and takes a closure to generate random instructions
pub fn new<F>(total_instructions: usize, random_instruction_generator: F) -> Mep<Ins>
where F : Fn() -> Ins {
let mut mep = Mep{instructions: Vec::with_capacity(total_instructions)};
for _ in 0..total_instructions {
mep.instructions.push(random_instruction_generator());
}
mep
}
}

这构建良好,并且似乎可以工作,但未实现预期的用例。我打算让用户访问 PRNG 的状态,该 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());
}

我创建了一个新的 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());
^~~

我发现 this post推断出 closure capture syntax已移入这种新形式。所以我尝试了这个:

#[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());
}

但是编译器提示:

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());
^~~~~~~~

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

最佳答案

您需要做的主要更改是将通用绑定(bind)从 Fn 更改为 FnMut。完成后,您还需要使参数 random_instruction_generator 可变:

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());
}

我还更改了您的 where 子句以使用更标准的格式并使用 mapcollect 而不是可变向量。

关于generics - 如何将某种通用闭包传递给函数以生成特定值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33135472/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com