为什么 Rust 在构造 nalgebra::MatrixN 时无法找出正确的 `from_iterator` 来使用?
Why is Rust unable to figure out the correct `from_iterator` to use when constructing a nalgebra::MatrixN?
我有一个结构定义为:
use nalgebra::{
allocator::Allocator, DefaultAllocator, Dim, DimName, MatrixN, RowVectorN, VectorN, U1,
}; // 0.22.0
pub struct Filter<Order: Dim + DimName>
where
DefaultAllocator:
Allocator<f64, Order, Order> + Allocator<f64, Order> + Allocator<f64, U1, Order>,
{
a: MatrixN<f64, Order>,
b: VectorN<f64, Order>,
c: RowVectorN<f64, Order>,
d: f64,
x: VectorN<f64, Order>,
}
在我的单元测试模块中,我想构造一个 Filter
:
的实例
mod tests {
use super::*;
use nalgebra::U2;
fn a_filter() -> Filter<U2> {
let a: MatrixN<f64, U2> = MatrixN::from_iterator([1., -0., 1., 0.].into_iter());
Filter {
a,
b: VectorN::zeros(),
c: RowVectorN::zeros(),
d: 0.,
x: VectorN::zeros()
}
}
}
调用MatrixN::from_iterator()
导致编译错误。调用 ::zeros()
:
时出现类似错误
error[E0034]: multiple applicable items in scope
--> src/lib.rs:22:44
|
22 | let a: MatrixN<f64, U2> = MatrixN::from_iterator([1., -0., 1., 0.].into_iter());
| ^^^^^^^^^^^^^ multiple `from_iterator` found
|
= note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>`
= note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>`
= note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>`
= note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>`
error[E0034]: multiple applicable items in scope
--> src/lib.rs:26:25
|
26 | b: VectorN::zeros(),
| ^^^^^ multiple `zeros` found
|
= note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>`
= note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>`
= note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>`
= note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>`
error[E0034]: multiple applicable items in scope
--> src/lib.rs:27:28
|
27 | c: RowVectorN::zeros(),
| ^^^^^ multiple `zeros` found
|
= note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>`
= note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>`
= note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>`
= note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>`
error[E0034]: multiple applicable items in scope
--> src/lib.rs:29:25
|
29 | x: VectorN::zeros(),
| ^^^^^ multiple `zeros` found
|
= note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>`
= note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>`
= note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>`
= note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>`
我不清楚为什么 Rust 无法找出正确的 from_iterator
来使用。是因为我必须在 Filter
的定义中指定 DefaultAllocator
吗?如果是这样,最干净的解决方法是什么?
TL; DR; A workaround 你的代码:
fn a_filter() -> Filter<U2> {
let a = MatrixN::<f64, U2>::from_iterator([1.0, -0., 1., 0.].iter().copied());
Filter {
a,
b: VectorN::<f64, U2>::zeros(),
c: RowVectorN::<f64, U2>::zeros(),
d: 0.,
x: VectorN::<f64, U2>::zeros()
}
}
你必须在 zeros()
的调用中指定顺序,而不是从 return 类型中猜测它。
from_iterator
有一个额外的问题,即 array::into_iter()
不是 return 对值的迭代器而是对值的引用,就像 iter()
(是的,是令人费解的,并且有一个 lint,IIRC),所以你需要添加一个 copied()
来获得正确的迭代器类型。
这是显示错误的最少代码 (playground):
use nalgebra::{
VectorN, U3
};
fn main() {
let x: VectorN<f64, U3> = VectorN::zeros();
}
错误是:
error[E0034]: multiple applicable items in scope
--> src/main.rs:5:40
|
5 | let x: VectorN<f64, U3> = VectorN::zeros();
| ^^^^^ multiple `zeros` found
|
= note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>`
= note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>`
= note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>`
= note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>`
如果你仔细看候选人,他们只是以下的全名:
candidate #1: Matrix<N, R, C, _>
candidate #2: Matrix<N, R, Dynamic, _>`
candidate #3: Matrix<N, Dynamic, C, _>`
candidate #4: Matrix<N, Dynamic, Dynamic, _>`
所以他们与 Dynamic
事情有关...如果您查看 documentation it is not very helpful, but if you look at the example in the zeros()
函数,它有一个提示:
let v = Vector3::<f32>::zeros();
let dv = DVector::<f32>::zeros(3);
let m = Matrix2x3::<f32>::zeros();
let dm = DMatrix::<f32>::zeros(2, 3);
等等...它不是需要 0 个参数吗?好吧,看看代码,虽然文档没有说明,但看起来 zeros()
接受的参数与泛型类型中的 Dynamic
一样多。而Vector3<T>
是Vector<T, U3>
的别名,DVector<T>
是Vector<T, Dynamic>
的别名等等。
您可能仍然认为编译器无论如何都可以推导出函数,因为 return 类型和参数编号对于 zero()
的每个版本都是不同的,但这不是编译器的工作方式: Rust 中没有函数重载。如果函数名称解析为多个函数,则为错误。
考虑显示类似错误的更简单的代码:
struct Foo<T> {
t: T,
}
impl Foo<u8> {
fn new() -> u8 {
0
}
}
impl Foo<u32> {
fn new() -> u32 {
0
}
}
fn main() {
let t: u8 = Foo::new(); // error!
}
请注意,如果两个函数 return 类型相同或不同,甚至它们是否具有相同数量的参数都没有关系,这始终是编译器错误。
我的代码的解决方法是:
fn main() {
let t: u8 = Foo::<u8>::new();
}
我有一个结构定义为:
use nalgebra::{
allocator::Allocator, DefaultAllocator, Dim, DimName, MatrixN, RowVectorN, VectorN, U1,
}; // 0.22.0
pub struct Filter<Order: Dim + DimName>
where
DefaultAllocator:
Allocator<f64, Order, Order> + Allocator<f64, Order> + Allocator<f64, U1, Order>,
{
a: MatrixN<f64, Order>,
b: VectorN<f64, Order>,
c: RowVectorN<f64, Order>,
d: f64,
x: VectorN<f64, Order>,
}
在我的单元测试模块中,我想构造一个 Filter
:
mod tests {
use super::*;
use nalgebra::U2;
fn a_filter() -> Filter<U2> {
let a: MatrixN<f64, U2> = MatrixN::from_iterator([1., -0., 1., 0.].into_iter());
Filter {
a,
b: VectorN::zeros(),
c: RowVectorN::zeros(),
d: 0.,
x: VectorN::zeros()
}
}
}
调用MatrixN::from_iterator()
导致编译错误。调用 ::zeros()
:
error[E0034]: multiple applicable items in scope --> src/lib.rs:22:44 | 22 | let a: MatrixN<f64, U2> = MatrixN::from_iterator([1., -0., 1., 0.].into_iter()); | ^^^^^^^^^^^^^ multiple `from_iterator` found | = note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>` = note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>` = note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>` = note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>` error[E0034]: multiple applicable items in scope --> src/lib.rs:26:25 | 26 | b: VectorN::zeros(), | ^^^^^ multiple `zeros` found | = note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>` = note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>` = note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>` = note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>` error[E0034]: multiple applicable items in scope --> src/lib.rs:27:28 | 27 | c: RowVectorN::zeros(), | ^^^^^ multiple `zeros` found | = note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>` = note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>` = note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>` = note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>` error[E0034]: multiple applicable items in scope --> src/lib.rs:29:25 | 29 | x: VectorN::zeros(), | ^^^^^ multiple `zeros` found | = note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>` = note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>` = note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>` = note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>`
我不清楚为什么 Rust 无法找出正确的 from_iterator
来使用。是因为我必须在 Filter
的定义中指定 DefaultAllocator
吗?如果是这样,最干净的解决方法是什么?
TL; DR; A workaround 你的代码:
fn a_filter() -> Filter<U2> {
let a = MatrixN::<f64, U2>::from_iterator([1.0, -0., 1., 0.].iter().copied());
Filter {
a,
b: VectorN::<f64, U2>::zeros(),
c: RowVectorN::<f64, U2>::zeros(),
d: 0.,
x: VectorN::<f64, U2>::zeros()
}
}
你必须在 zeros()
的调用中指定顺序,而不是从 return 类型中猜测它。
from_iterator
有一个额外的问题,即 array::into_iter()
不是 return 对值的迭代器而是对值的引用,就像 iter()
(是的,是令人费解的,并且有一个 lint,IIRC),所以你需要添加一个 copied()
来获得正确的迭代器类型。
这是显示错误的最少代码 (playground):
use nalgebra::{
VectorN, U3
};
fn main() {
let x: VectorN<f64, U3> = VectorN::zeros();
}
错误是:
error[E0034]: multiple applicable items in scope
--> src/main.rs:5:40
|
5 | let x: VectorN<f64, U3> = VectorN::zeros();
| ^^^^^ multiple `zeros` found
|
= note: candidate #1 is defined in an impl for the type `nalgebra::Matrix<N, R, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, C>>::Buffer>`
= note: candidate #2 is defined in an impl for the type `nalgebra::Matrix<N, R, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, R, nalgebra::Dynamic>>::Buffer>`
= note: candidate #3 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, C, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, C>>::Buffer>`
= note: candidate #4 is defined in an impl for the type `nalgebra::Matrix<N, nalgebra::Dynamic, nalgebra::Dynamic, <nalgebra::DefaultAllocator as nalgebra::allocator::Allocator<N, nalgebra::Dynamic, nalgebra::Dynamic>>::Buffer>`
如果你仔细看候选人,他们只是以下的全名:
candidate #1: Matrix<N, R, C, _>
candidate #2: Matrix<N, R, Dynamic, _>`
candidate #3: Matrix<N, Dynamic, C, _>`
candidate #4: Matrix<N, Dynamic, Dynamic, _>`
所以他们与 Dynamic
事情有关...如果您查看 documentation it is not very helpful, but if you look at the example in the zeros()
函数,它有一个提示:
let v = Vector3::<f32>::zeros();
let dv = DVector::<f32>::zeros(3);
let m = Matrix2x3::<f32>::zeros();
let dm = DMatrix::<f32>::zeros(2, 3);
等等...它不是需要 0 个参数吗?好吧,看看代码,虽然文档没有说明,但看起来 zeros()
接受的参数与泛型类型中的 Dynamic
一样多。而Vector3<T>
是Vector<T, U3>
的别名,DVector<T>
是Vector<T, Dynamic>
的别名等等。
您可能仍然认为编译器无论如何都可以推导出函数,因为 return 类型和参数编号对于 zero()
的每个版本都是不同的,但这不是编译器的工作方式: Rust 中没有函数重载。如果函数名称解析为多个函数,则为错误。
考虑显示类似错误的更简单的代码:
struct Foo<T> {
t: T,
}
impl Foo<u8> {
fn new() -> u8 {
0
}
}
impl Foo<u32> {
fn new() -> u32 {
0
}
}
fn main() {
let t: u8 = Foo::new(); // error!
}
请注意,如果两个函数 return 类型相同或不同,甚至它们是否具有相同数量的参数都没有关系,这始终是编译器错误。
我的代码的解决方法是:
fn main() {
let t: u8 = Foo::<u8>::new();
}