- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
使用 rustc 1.10.0
,我正在尝试编写一些绕过盒装闭包的代码——最终目标是按程序生成分形动画。现在我有一些像这样的函数签名:
pub fn interpolate_rectilinear(width: u32, height: u32, mut min_x: f64, mut max_x: f64, mut min_y: f64, mut max_y: f64)
-> Box<Fn(u32, u32) -> Complex64 + Send + Sync + 'static> { ... }
pub fn interpolate_stretch(width: u32, height: u32, mut min_x: f64, mut max_x: f64, mut min_y: f64, mut max_y: f64)
-> Box<Fn(u32, u32) -> Complex64 + Send + Sync + 'static> { ... }
pub fn parallel_image<F>(width: u32, height: u32, function: &F, interpolate: &Box<Fn(u32, u32) -> Complex64 + Send + Sync>, threshold: f64)
-> ImageBuffer<image::Luma<u8>, Vec<u8>>
where F: Sync + Fn(Complex64) -> Complex64
{ ... }
pub fn sequential_image<F>(width: u32, height: u32, function: &F, interpolate: &Box<Fn(u32, u32) -> Complex64>, threshold: f64)
-> ImageBuffer<image::Luma<u8>, Vec<u8>>
where F: Fn(Complex64) -> Complex64
{ ... }
在二进制文件中一次为一个图像运行这段代码没有问题:
let interpolate = interpolate_rectilinear(width, height, -1.0, 1.0, -1.0, 1.0);
let image = parallel_image(width * 2, height * 2, &default_julia, &interpolate, 2.0);
但是,我想确保我的串行和并行图像生成都产生相同的结果,所以我编写了以下测试函数:
#[test]
fn test_serial_parallel_agree() {
let (width, height) = (200, 200);
let threshold = 2.0;
let interpolate = interpolate_stretch(width, height, -1.0, 1.0, -1.0, 1.0);
assert!(parallel_image(width, height, &default_julia, &interpolate, threshold)
.pixels()
.zip(sequential_image(width, height, &default_julia, &interpolate, threshold)
.pixels())
.all(|(p, s)| p == s));
}
这拒绝编译,我就是想不通。它给出的错误如下:
> cargo test
Compiling julia-set v0.3.0
src/lib.rs:231:66: 231:78 error: mismatched types [E0308]
src/lib.rs:231 .zip(sequential_image(width, height, &default_julia, &interpolate, threshold)
^~~~~~~~~~~~
src/lib.rs:229:9: 233:36 note: in this expansion of assert! (defined in <std macros>)
src/lib.rs:231:66: 231:78 help: run `rustc --explain E0308` to see a detailed explanation
src/lib.rs:231:66: 231:78 note: expected type `&Box<std::ops::Fn(u32, u32) -> num::Complex<f64> + 'static>`
src/lib.rs:231:66: 231:78 note: found type `&Box<std::ops::Fn(u32, u32) -> num::Complex<f64> + Send + Sync>`
error: aborting due to previous error
Build failed, waiting for other jobs to finish...
error: Could not compile `julia-set`.
我真的不知道那里发生了什么。我不知道为什么我需要在插值函数的盒装返回类型中手动标记 Send
和 Sync
,而编译器通常会自动派生这些特征。不过,我只是不断添加编译器建议的标记,直到一切正常为止。
真正的问题是,虽然我想我有一个很好的猜测为什么你不能只标记一个盒装闭包 'static
,但我不知道在这种情况下什么需要生命周期或如何修复它。
我确实猜到问题可能是我试图同时引用两个读取借用的闭包(这应该没问题,但我很绝望);无论如何,将 interpolate
包装在 Rc
中会产生完全相同的错误,所以这不是问题所在。
最佳答案
问题其实就在这里:
pub fn sequential_image<F>(
...,
interpolate: &Box<Fn(u32, u32) -> Complex64>,
...) -> ...
interpolate
不期望 &Box<Fn(u32, u32) -> Complex64 + Send + Sync>
,并且 Rust 在处理所有这些复杂性的变化方面非常糟糕。
一个解决方案是在它被调用的地方进行转换:
sequential_image(width, height, &default_julia,
&(interpolate as Box<Fn(u32, u32) -> Complex64>),
threshold)
但这需要 sequential_image
的值大小写而且非常丑陋。
更好的方法是只固定 sequential_image
的参数一些更通用且更容易让编译器推理的东西:基本指针。
pub fn sequential_image<F>(
...,
interpolate: &Fn(u32, u32) -> Complex64,
...) -> ...
现在你可以调用它了
sequential_image(width, height, &default_julia,
&*interpolate,
threshold)
并且编译器可以自己完成所有的变体魔术。
关于closures - 盒装 Fn 仅在测试时才需要 lifetime 'static?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38704415/
我是一名优秀的程序员,十分优秀!