|
| 1 | +- Feature Name: `assoc_math_consts` |
| 2 | +- Start Date: 2023-04-17 |
| 3 | +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) |
| 4 | +- Rust Issue: [rust-lang/rust#0000](https://github.com/rust-lang/rust/issues/0000) |
| 5 | + |
| 6 | +# Summary |
| 7 | +[summary]: #summary |
| 8 | + |
| 9 | +Add the constants in std::f32::consts and std::f64::consts as associated |
| 10 | +constants to the f32 and f64 types (e.g. f32::PI). |
| 11 | + |
| 12 | +# Motivation |
| 13 | +[motivation]: #motivation |
| 14 | + |
| 15 | +Currently mathematical constants such as π live in |
| 16 | +std::{f32, f64}::consts. This is difficult to type and read if written out in full everywhere. |
| 17 | +Consider |
| 18 | +```rust |
| 19 | +assert_eq!(std::f32::consts::FRAC_PI_4.sin(), std::f32::consts::FRAC_1_SQRT_2); |
| 20 | +``` |
| 21 | +vs |
| 22 | +```rust |
| 23 | +assert_eq!(f32::FRAC_PI_4.sin(), f32::FRAC_1_SQRT_2); |
| 24 | +``` |
| 25 | +While it is possible to `use std::f32::consts as f32c;` or similar, it could be cumbersome to do that in every file |
| 26 | +in a project which uses mathematical constants heavily. |
| 27 | + |
| 28 | +Also new users of Rust might expect mathematical constants to be there. |
| 29 | +Currently |
| 30 | +NAN, INFINITY, etc. are associated constants, and it might |
| 31 | +be confusing for f32::NAN to exist, but not f32::PI. |
| 32 | + |
| 33 | +# Guide-level explanation |
| 34 | +[guide-level-explanation]: #guide-level-explanation |
| 35 | + |
| 36 | +When writing code which uses mathematical constants, the associated constants in f32 and f64 can be used. For example, |
| 37 | +the function f(*x*) = (π/*e*)<sup>*x*</sup> can be written as: |
| 38 | + |
| 39 | +```rust |
| 40 | +fn f(x: f32) -> f32 { |
| 41 | + (f32::PI / f32::E).powf(x) |
| 42 | +} |
| 43 | +``` |
| 44 | + |
| 45 | +# Reference-level explanation |
| 46 | +[reference-level-explanation]: #reference-level-explanation |
| 47 | + |
| 48 | +The following constants will be added with their values taken from |
| 49 | +the respective constants in std::f32::consts and std::f64::consts. |
| 50 | + |
| 51 | +- f32::{PI, TAU, FRAC\_PI\_2, FRAC\_PI\_3, FRAC\_PI\_4, FRAC\_PI\_6, FRAC\_PI\_8, FRAC\_1\_PI, |
| 52 | +FRAC\_2\_PI, FRAC\_2\_SQRT\_PI, SQRT\_2, FRAC\_1\_SQRT\_2, E, LOG2\_E, LOG2\_10, LOG10\_E, LOG10\_2, |
| 53 | +LN\_2, LN\_10} |
| 54 | +- f64::{PI, TAU, FRAC\_PI\_2, FRAC\_PI\_3, FRAC\_PI\_4, FRAC\_PI\_6, FRAC\_PI\_8, FRAC\_1\_PI, |
| 55 | +FRAC\_2\_PI, FRAC\_2\_SQRT\_PI, SQRT\_2, FRAC\_1\_SQRT\_2, E, LOG2\_E, LOG2\_10, LOG10\_E, LOG10\_2, |
| 56 | +LN\_2, LN\_10} |
| 57 | + |
| 58 | +# Drawbacks |
| 59 | +[drawbacks]: #drawbacks |
| 60 | + |
| 61 | +Currently it is not possible to `use` associated constants, so in order to `use` mathematical constants, |
| 62 | +it will still be necessary to refer to them by their paths in std. |
| 63 | + |
| 64 | +Even if `use`-ing associated constants does become possible in a future version of Rust, |
| 65 | +it will likely never be possible or a good idea to do `use f32::*;` whereas |
| 66 | +`use std::f32::consts::*;` is perhaps more reasonable (although, it's worth mentioning |
| 67 | +that more mathematical constants could be added in future versions of Rust, so using `*` |
| 68 | +is probably not a good idea in general). |
| 69 | + |
| 70 | +This proposal would add many more items to the `f32` and `f64` types, which might not be desirable. |
| 71 | + |
| 72 | +# Rationale and alternatives |
| 73 | +[rationale-and-alternatives]: #rationale-and-alternatives |
| 74 | + |
| 75 | +- The mathematical constants in std could be (planned to be) deprecated. |
| 76 | + The drawback as mentioned above is that f32::PI, etc. are not `use`-able. |
| 77 | + The benefit is that there would be a clear "preferred" path for mathematical constants. |
| 78 | +- We could create a trait similar to [num::traits::FloatConst](https://docs.rs/num/0.4.0/num/traits/trait.FloatConst.html) |
| 79 | + which houses these constants. The benefits are that the constants can be used in a generic |
| 80 | + context and we wouldn't be crowding the `f32` and `f64` types. |
| 81 | + The downside would be that adding a new constant would be a breaking change |
| 82 | + for any user types implementing the trait (unless it was made externally unimplementable |
| 83 | + via the usual "hack" of a pub trait in a private module). |
| 84 | +- Creating a type for each constant, e.g. `struct Pi;` then implementing |
| 85 | + `From<f32>`, `From<f64>`, etc. for them (and perhaps also `Add<f32>`, etc.). |
| 86 | + The benefits are that these could be used in generic contexts, |
| 87 | + wouldn't be crowding the `f32`/`f64` types, and |
| 88 | + non-std types could add `From<T>` implementations |
| 89 | + for the constants. The downsides are that `f32::from(Pi)` (which you |
| 90 | + might end up needing to use in a lot of cases to get type inference to work) |
| 91 | + is a bit less "ergonomic" than `f32::PI`, the names would need to change |
| 92 | + from `CONSTANT_CASE` to `TypeCase`, and it might be less intuitive |
| 93 | + (especially for beginners) that mathematical constants are structs and not |
| 94 | + constants. |
| 95 | + |
| 96 | + |
| 97 | +# Prior art |
| 98 | +[prior-art]: #prior-art |
| 99 | + |
| 100 | +- The crates `half` and `fixed` have these as associated constants on their types. |
| 101 | +- RFC 2700 originally proposed to do this, but since it was "met with mild resistance", |
| 102 | + it was decided that it would be left for a later RFC since the focus of 2700 |
| 103 | + was on adding integral associated constants (e.g. u32::MAX). |
| 104 | + |
| 105 | +# Unresolved questions |
| 106 | +[unresolved-questions]: #unresolved-questions |
| 107 | + |
| 108 | +# Future possibilities |
| 109 | +[future-possibilities]: #future-possibilities |
| 110 | + |
| 111 | +- In the future, especially if associated constants become `use`-able, |
| 112 | + we could deprecate std::{f32, f64}::consts. |
0 commit comments