type alias
Consider to remove:
pub type Complex32 = Complex<f32>;
pub type Complex64 = Complex<f64>;
in favor of:
#[allow(non_camel_case_types)]
pub type c32 = Complex<f32>;
#[allow(non_camel_case_types)]
pub type c64 = Complex<f64>;
It might seem controversial, but:
- from import one can already see: this is about complex numbers,
- perfectly fits in the scheme
u64 i64 f64 c64, - to me it feels more ergonomic,
-
c64::new(1.0,2.0)is a already a pain compared to1+2i, - stuff will actually fit into the 80 columns limit.
Another reason is that rustc could start to lint against
use num::complex::Complex64 as c64;
because of a non camel case type. It would be an ergonomic disaster if one needs to turn that off explicitly.
For comparison, see noisy_float:
pub type N32 = NoisyFloat<f32, NumChecker>;
pub type N64 = NoisyFloat<f64, NumChecker>;
pub type R32 = NoisyFloat<f32, FiniteChecker>;
pub type R64 = NoisyFloat<f64, FiniteChecker>;
pub fn n32(value: f32) -> N32 { N32::new(value) }
pub fn n64(value: f64) -> N64 { N64::new(value) }
pub fn r32(value: f32) -> R32 { R32::new(value) }
pub fn r64(value: f64) -> R64 { R64::new(value) }
(Docs stripped and reformatted for vertical space by me)
So num-complex would add:
pub fn c32(re: f32, im: f32) -> Complex32;
pub fn c64(re: f64, im: f64) -> Complex64;
And then you'd just be able to write let x: Complex64 = c64(1, 2).
If we were to add short aliases, I would want to at least conform to convention as C64 and C32. These are not builtin types like f64 etc., and I'd rather not pretend they were. Notably, they can't support literals, and they also don't have compatibility with C calling conventions, which I would hope to see from a builtin complex type.
However, since import renaming is possible, I'm inclined to leave it as-is. Even using your own private type alias would still be completely compatible with all other uses of Complex<f64>. The "ergonomic disaster" of lints against lower-case c64 is your own choice to defy convention, but I don't think there's a strong reason for us to do that in num-complex.
I see a little more value in having pub fn c32 and c64, as this idea both conforms to naming convention and makes the common constructors easier to use.
And then you'd just be able to write
let x: Complex64 = c64(1, 2).
You shouldn't need the : Complex64 type ascription, but maybe you were just illustrating the result.
This won't quite work though, because the literals 1 and 2 have strictly integral types. We could make it generic to actually offer something unique, rather than just wrapping Complex::new, like:
pub fn c64<T: Into<f64>>(re: T, im: T) -> Complex64 {
Complex64::new(re.into(), im.into())
}
And perhaps also something like:
pub fn to_c64<T: ToPrimitive>(re: &T, im: &T) -> Option<Complex64> {
if let Some(re) = re.to_f64() {
if let Some(im) = im.to_f64() {
return Some(c64(re, im));
}
}
None
}