ndarray
ndarray copied to clipboard
Use references for scalar operands
It would be useful for me to be able to use references to scalars instead of owned instances when performing operations on arrays.
e.g., this fails:
let arr1 = array!([1, 2, 3]);
let four: i32 = 4;
let arr2 = arr1 + &four; //error
I naively tried modifying the ops macros to accept references but kept getting a conflicting implementation error. It seems that the compiler is worried that someone will come along an add an implementation to StaticOperand for reference types:
= note: downstream crates may implement trait `impl_ops::ScalarOperand` for type `&_`
...which is strange because there's a 'static type bound on ScalarOperand?
In any case, if anyone has any guidance on how to proceed, I'd greatly appreciate it! I'm happy to open a PR with a nudge in the right direction.
I assume that you tried to add something like the following:
impl<'a, A, S, D, B> $trt<&'a B> for ArrayBase<S, D>
where
A: Clone + $trt<&'a B, Output = A>,
S: DataOwned<Elem = A> + DataMut,
D: Dimension,
B: ScalarOperand,
{
...
}
The problem is that the following implementation already exists:
impl<A, S, D, B> $trt<B> for ArrayBase<S, D>
where
A: Clone + $trt<B, Output = A>,
S: DataOwned<Elem = A> + DataMut,
D: Dimension,
B: ScalarOperand,
{
...
}
So, a downstream crate could do the following:
#[derive(Clone)]
struct Struct {}
impl ndarray::ScalarOperand for Struct {}
impl ndarray::ScalarOperand for &'static Struct {}
which would result in conflicting implementations of Add<&'static Struct> for ArrayBase<S, D>, Mul<&'static Struct> for ArrayBase<S, D>, etc.
It looks like you already found the solution in #1201 that I'd suggest -- remove the 'static bound from ScalarOperand and implement ScalarOperand for references. You can implement ScalarOperand for &i32, &f32, etc., or for &T where T: ScalarOperand.