最近我问到如何将一堆具有相同签名的闭包放入Rust中的向量中.来自Haskell的背景,看起来有点复杂,Rust封装每个都有自己独特的类型,需要一个特征来代表它们.在Haskell中,lambda是通过其签名键入的,如果签名相同,则类型相同.
Rust闭包和Haskell lambda函数之间是否存在语义差异导致这些差异?
编者注:这个问题在Rust 1.0之前被问过,并且从那时起一些语法发生了变化,但基本概念仍然存在.一些答案已针对Rust 1.0语法进行了更新.
我是Rust的新手,并尝试使用在JavaScript,Python等方面无关紧要的闭包,但我遇到Rust的终身问题.我理解错误信息,但它让我相信我想要做的事情在Rust中非常难.
我只是想创建一个函数数组a,这样
a[0] 是返回0的函数a[1] 是返回1的函数a[9] 是函数返回9我试过了:
fn main() {
let a : [||->uint, ..10];
for i in range(0u, 10) {
a[i] = ||{i};
}
println!("{} {} {}", a[1](), a[5](), a[9]())
}
Run Code Online (Sandbox Code Playgroud)
但我得到了一生的错误.a由于生命周期不能超过while块,所以报告的错误是"无法推断由于要求冲突的适当生命周期",因此闭包不能超过它们的堆栈帧,这当然是因为我正在调用它们println!.
我敢肯定必须有一种方法来构建这个函数数组,但是如何?
正如这篇文章所说,你可以像这样创建一个闭包向量:
let mut xs: Vec<Box<dyn Fn((i32, i32)) -> (i32, i32)>> = vec![
Box::new(move |(x, y)| (y, x)),
Box::new(move |(x, y)| (1 - y, 1 - x)),
];
Run Code Online (Sandbox Code Playgroud)
但是为什么不能使用以下方法附加到它:
xs.append(Box::new(move |(x, y)| (2 - y, 2 - x)));
Run Code Online (Sandbox Code Playgroud)
这引发了错误:
|
162 | xs.append(Box::new(move |(x, y)| (2 - y, 2 - x)));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected mutable reference, found struct `std::boxed::Box`
|
= note: expected mutable reference `&mut std::vec::Vec<std::boxed::Box<dyn std::ops::Fn((i32, i32)) -> (i32, i32)>>`
found struct `std::boxed::Box<[closure@src/lib.rs:162:22: 162:50]>`
Run Code Online (Sandbox Code Playgroud)