paholg / dimensioned Goto Github PK
View Code? Open in Web Editor NEWCompile-time dimensional analysis for various unit systems using Rust's type system.
Home Page: https://crates.io/crates/dimensioned
License: MIT License
Compile-time dimensional analysis for various unit systems using Rust's type system.
Home Page: https://crates.io/crates/dimensioned
License: MIT License
(I'm sorry. I'm very new to rust and having a hard time understanding the type system.)
What I'm trying to achieve is a method on a struct that accepts any temperature, and uses it in a calculation to return a unitless value.
I'm trying to do something like this:
impl TemperatureDependence for MyStruct {
fn apply<T>(&self, n :Vector3<f64>, temperature :T) -> Vector<f64>
where T :Temperature {
// --snip--
// this should be unitless.. not sure if I should use dimensioned::si::Unitless...
let f :f64 = (temperature - 20 * si::K) / si::K;
// --snip--
// returns a vector based on this
}
}
But I get the error:
binary operation
-
cannot be applied to typeT
note:T
might need a bound forstd::ops::Sub
I feel like i'm missing something, because i don't actually want to make this THAT generic. I feel like any type that implements trait Temperature
should be able to be converted into Kelvin... so what gives? How do i do this?
Thanks in advance.
I'm working on the rmdim
branch, and have come across something I don't understand.
The issue crops up in this test, partially reproduced here:
let x = 2.0*M;
let x2 = 4.0*M*M;
assert_eq!(x2, x.powi(P2::new()));
assert_eq!(x, x2.sqrt());
// fixme: This fails. Why? It should be the same as calling sqrt().
// assert_eq!(x, x2.root(P2::new()));
I can call x2.sqrt()
with no issues. That implementation looks like this:
use typenum::P2;
impl<T> Sqrt for T
where T: Root<P2>
{
type Output = <T as Root<P2>>::Output;
fn sqrt(self) -> Self::Output {
self.root(P2::new())
}
}
However, if I try to call x2.root(P2::new())
, I get an infinite recursion issue. But that's all that sqrt()
does.
Also, the Pow
trait is implemented essentially identically to the Root
trait, and it has no issues.
Those impls are in the macro, here.
It would be lovely to implement std::iter::Sum
for types that also implement it, so I could use vec.iter().sum().
There's a value_unsafe parameter, but it's unclear to me if that's the "right" way to do things if you just want to extract the value (sans the units). It'd be nice if this were explicitly stated somewhere, too, so that new users can discover it without asking.
Thanks!
I would like to ensure that any interface that lets you take actions where units are not checked is clearly labeled.
For example, in v0.5 of dimensioned, there is a map
function that lets you apply a function to the underlying value. In the rewrite, I am looking at having two functions, map
and map_unsafe
. Both do the same thing, but the new map
is only defined when dealing with dimensionless quantities so you have no units to mess up.
I would like direct exposure to the underlying value to follow a similar naming convention, but the word "unsafe" has pretty clear memory-safety connotations in the Rust ecosystem and I would like to avoid it.
Thoughts?
The trouble is that cargo fmt
is currently breaking the code. See:
Presumably this is a newish bug in cargo, since the last commit on master passed, but for now it's making pull requests fail.
f32
, f64
, etc. have functions called max
and min
that are defined to return the higher/lower non-NaN number. AFAICT it's not possible to actually call them on unit types without manually unpacking with either .value_raw
or creating a dimensionless quantity and derefing. Please consider adding max
and min
functions on the unit types if the primitive type has them.
Change dimensioned to use #![no_std]
so that it may be used by other #![no_std]
crates. Currently the only requirement appears to be the DimToString
functionality and if it can be changed to work with core::fmt::Formatter
then the current std
requirements could be removed.
Would be nice to have Thomson and Dalton available as derived units. The definition can be found on this page:
https://en.wikipedia.org/wiki/Thomson_(unit)
Barring that, it'd be helpful if a guide existed on how to derive units yourself.
Hello,
I'd like to investigate dimensioned, but I need f256 support for the quantum mechanics work I'd like to do.
Planck's constant is 6.62607015 × 10−34 so even f128 isn't good enough.
If you give me a few pointers I could take a stab at adding f256 support to dimensioned.
Thanks!
Instead of si::M
, I would prefer to stick to the original letter case, i.e., si::m
. I suppose it is not Rust-style, however, the correct letter case would avoid some clashes of derived and combined units. See the following:
Symbols are case-sensitive, so the meaning of an SI symbol can be changed if you substitute an uppercase letter for a lowercase letter.
Correct: mm (for millimetre, which means 1/1000 of a metre)
Incorrect: MM or Mm (M is the symbol for the prefix mega-, which means one million; a megametre is a million metres)
I have been looking into how to make converting between unit systems as painless as possible.
Here is an example showing where I am so far.
Basically, every unit system would have its own From
trait that would let you convert from it into another system.
I have two main issues with this method
It's cumbersome to implement. It's not so bad for systems of two units, but once you get up to the 7 that SI has, or have to deal with systems that expression dimensions in different powers (such as CGS, or a system with gallons as a base unit), it gets pretty messy. I don't mind for the unit systems that ship with dimensioned, but it should be easy for users to create their own systems and convert between them.
It lacks genericity. In order to implement the From
traits, I had to restrict it to types that can be multiplied by an f64
(could have also chosen f32
) and not change type. What's worse, is that once implemented for, say, f64
, I don't believe it possible to also implement the conversion for f32
. At least, not without abandoning all genericity and doing:
impl<Meter: Integer, Second: Integer> ms::FromMS<Meter, Second> for fs::FS<Meter, Second> {
fn from_ms(from: Dim<ms::MS<Meter, Second>, f32>) -> Dim<Self, f32> {
Dim::new(from.0 * 3.281)
}
}
This would restrict Dim
to only being used with primitives if you want access to unit conversions. One could argue that that's how Dim
should be used, but it requires every container you put Dim
in to be incredibly generic. I have yet to see a matrix or vector library that I have not written that is generic enough to be used with Dim
s.
Apologies if this is documented somewhere and I can't find it. I'm trying to write a distance function that currently returns a distance in meters. I'd like to use this crate to add type safety to this return value, with the eventual goal of representing the distance in feet or other units, or combining it with time units to create speeds/velocities.
Your example shows how to write a speed function. Would you mind demonstrating how one might write a distance function? I.e.:
fn distance(p1: Point, p2: Point) -> f64 {
// Assume we crunch some numbers and get a distance in meters
meters
}
I tried making the f64
a Length
, but additional type parameters are needed, and if I try braking the build to see what type signature is expected, I get a huge ugly thing that doesn't really give me any clarity. :)
Thanks.
It would be lovely to be able to take the absolute value of a dimensioned number. I am not sure how to do this best, but would be happy to work on a pull request. Sadly, abs does not seem to be in a trait in the standard library, so we'd need specific implementations for basically every primitive type as far as I can see?
NB: I'm entirely prepared to be told I'm doing it wrong.
I have created a unit system with a single dimension to represent pixels in an image like so:
pub mod pixel_space {
make_units! {
PIX;
ONE: Unitless;
base {
PX: Pixel, "px", Length;
}
derived {
PX2: Pixel2 = (Pixel * Pixel), Area;
}
constants {
}
fmt = true;
}
pub use self::f64consts::*;
}
In a unit test I then attempt to create a Pixel<isize>
- as we'll always have an integral number of pixels -
like so:
#[cfg(test)]
mod test {
use super::pixel_space::{Pixel, PX};
#[test]
fn create_integer_value() {
let x : Pixel<isize> = 42 * PX;
assert_eq!(x.value_unsafe, 42);
}
}
Which promptly fails to compile with:
$ cargo test
Compiling firkin v0.1.0 (file:///home/tcc/projects/firkin)
error[E0277]: the trait bound `{integer}: std::ops::Mul<units::pixel_space::PIX<f64, dim::<unnamed>::TArr<dim::<unnamed>::PInt<dim::<unnamed>::UInt<dim::<unnamed>::UTerm, dim::<unnamed>::B1>>, dim::<unnamed>::ATerm>>>` is not satisfied
--> src/units.rs:29:32
|
29 | let x : Pixel<isize> = 42 * PX;
| ^^^^^^^ the trait `std::ops::Mul<units::pixel_space::PIX<f64, dim::<unnamed>::TArr<dim::<unnamed>::PInt<dim::<unnamed>::UInt<dim::<unnamed>::UTerm, dim::<unnamed>::B1>>, dim::<unnamed>::ATerm>>>` is not implemented for `{integer}`
|
= help: the following implementations were found:
<dim::<unnamed>::TArr<V, A> as std::ops::Mul<Rhs>>
<bool as std::ops::Mul<dim::si::SI<V, U>>>
<bool as std::ops::Mul<dim::ucum::UCUM<V, U>>>
<bool as std::ops::Mul<dim::mks::MKS<V, U>>>
and 298 others
error: aborting due to previous error
error: Could not compile `firkin`.
Note that doing the same thing with a floating-point value works as expected:
#[cfg(test)]
mod test {
use super::pixel_space::{Pixel, PX};
#[test]
fn create_real_value() {
let x : Pixel<f64> = 42.0 * PX;
assert_eq!(x.value_unsafe, 42.0);
}
}
Am I using it wrong, or is this an issue?
I can use your (paholg) suggestion to divide by 1 using the expected units, then visually inspect the formatted String to see if any mks values are present. If they are, then the units were unexpected and I know I have a problem with my math. Thanks dimensioned!
But... I believe this doesn't scale. Is it possible to get a public method to determine if the Dimensioned value is unitless?
Then I wouldn't have to visually inspect things to make sure only my expected type is there.
Alternatively I could format the Dimensioned value to a string and then parse the string to see if other units are there.
I'm just nervous about having to perform a mental visual check on all results.
Thoughts?
Right now, a constant is defined for each unit we create. They tend to have names like m
for 1 meter.
There's a couple things I don't like about this.
First, it goes against Rust's naming convention that constants should be uppercase -- but I think I like making these constants uppercase even less.
Second, it requires us to choose a "blessed" primitive when creating a unit system. Right now it's been f64
, but what if you want f32
or something else? Well then you have to make your own anyway.
Recent changes to dimensioned mean that instead of Dim<Meter, f64>
you write Meter<f64>
, which means it's much cleaner to construct units without the consts.
The old way:
let x: Dim<Meter, f64> = Dim::new(3.4);
The new way:
let x = Meter::new(3.4);
This increase in constructor ergonomics makes want to get rid of pre-defining constants, but I figured I'd post this issue first in case anyone else has thoughts on the matter.
It came up in #41 that it would be nice to have functions like abs()
, sqrt()
, etc. implemented on $System<f64, U>
(and friends) directly, and not just through traits, so that they could be called without the traits in scope.
A pedantic breaking changing. Please close if you believe this is too much breakage.
The current struct has dimensions, but it seems awkward to also call it Dim
. I believe the current Dim
struct should be renamed to Quantity
. Given a system of quantities (SI) each quantity can be defined in terms of a quantity dimension and base quantity.
Should these be in a separate crate? I would like to derive the Radians unit from SI (m * m^-1
), and have a conversion to/from Degrees. Then also make trigonometry functions with the correct units, as I do in cgmath::angle
.
If we have pub struct Dim<D: Dimension, V>(pub V, pub PhantomData<D>);
then we can't do something like type MPS = Quot<Meter, Second>;
and have it work properly.
So for now, we will declare Dim
with pub struct Dim<D, V>(pub V, pub PhantomData<D>);
(and also remove the constraint elsewhere where necessary).
Essentially, once this compiles, we can re-add the constraint (which will, unfortunately, be a breaking change).
I realize that the documentation for ucum says:
There are a few classifications of units that UCUM defines but that it does not make sense to define here, and so we do not.
…
Units that require conversions that involve more than multiplication. These include some temperature units (such as degrees Celcius)
But easy conversion between Celsius and Kelvin is something I expected to be able to do. Perhaps it doesn’t make sense to implement it in the ucum unit system, but perhaps having an additional unit system would make sense. (maybe it should be called “misc”?).
Here is my pathetic attempt to implement this (which doesn’t compile).
mod ucum_plus {
make_units! {
UCUM_PLUS;
ONE: Unitless;
base {
DEGC: DegreeCelsius, "°C", Temperature;
}
derived {
}
constants {
}
fmt = true;
}
pub use self::f64consts::*;
use dim::typenum::{Integer, Z0};
use std::convert::From;
use dim::ucum;
impl<V, Temperature> From<ucum::UCUM<V, tarr![Z0, Z0, Z0, Z0, Temperature, Z0, Z0]>>
for UCUM_PLUS<<<<V as dim::typenum::Pow<i32>>::Output as std::ops::Sub<f64>>::Output as dim::typenum::Pow<i32>>::Output, tarr![Temperature]>
where
V: Mul<f64> + dim::typenum::Pow<i32>,
Temperature: Integer,
<V as dim::typenum::Pow<i32>>::Output : Sub<f64>,
<<V as dim::typenum::Pow<i32>>::Output as std::ops::Sub<f64>>::Output : dim::typenum::Pow<i32>
{
fn from(other: ucum::UCUM<V, tarr![Z0, Z0, Z0, Z0, Temperature, Z0, Z0]>) -> Self {
let pow = Temperature::to_i32();
let kelvin = other.value_unsafe.powi(-pow);
let celcius = kelvin - 273.15;
UCUM_PLUS::new( celcius.powi(pow) )
}
}
impl<V, Temperature> Into<ucum::UCUM<<<<V as dim::typenum::Pow<i32>>::Output as std::ops::Sub<f64>>::Output as dim::typenum::Pow<i32>>::Output, tarr![Z0, Z0, Z0, Z0, Temperature, Z0, Z0]>>
for UCUM_PLUS<V, tarr![Temperature]>
where
V: Mul<f64> + dim::typenum::Pow<i32>,
Temperature: Integer,
<V as dim::typenum::Pow<i32>>::Output : Add<f64>,
<<V as dim::typenum::Pow<i32>>::Output as std::ops::Add<f64>>::Output : dim::typenum::Pow<i32>
{
fn into(self) -> ucum::UCUM<<<<V as dim::typenum::Pow<i32>>::Output as std::ops::Sub<f64>>::Output as dim::typenum::Pow<i32>>::Output, tarr![Z0, Z0, Z0, Z0, Temperature, Z0, Z0]> {
let pow = Temperature::to_i32();
let celsius = self.value_unsafe.powi(-pow);
let kelvin = celsius + 273.15;
ucum::UCUM::new( kelvin.powi(pow) )
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn conversion_test() {
let c = 30. * DEGC;
let k = 400. * ucum::K;
let diff = k - c;
assert_eq!(*(diff/K), 96.85);
}
}
}
A basic unit would be a bit
.
I would like using dimensioned to be as painless as possible. It should feel like you're working with primitives, only they yell at you more when you make mistakes.
If you have any thoughts on the ergonomics of dimensioned, in regards to anything, please add them here!
Currently, we have aliases that look like this:
pub type Meter = SI<P1, Z0, Z0, Z0, Z0, Z0, Z0>;
which requires you to use it like this:
fn length() -> Dim<Meter, f64> {
5.7 * m
}
I would like to switch the aliases to look like this:
pub type Meter<V> = Dim<SI<P1, Z0, Z0, Z0, Z0, Z0, Z0>, V>;
so that the above function could be replaced with:
fn lenth() -> Meter<f64> {
5.7 * m
}
I am not certain that this won't cause issues in other places (especially in defining derived units, which I'm currently working on as well), but barring that I'm not 100% sure it's a good idea.
It makes dimensioned types cleaner to view and easier to type.
It makes error messages more cryptic (they won't change, but they contain Dim
which users will no longer need to deal with directly).
It also might make some things more confusing. I'm not sure exactly.
It is important for both unit systems and users of them to be able to conveniently define derived units. Right now, you can do
type Newton = SI<P1, P1, N2>;
but that isn't great. I have a macro in progress that can turn
type Newton = derived!(Meter * Kilogram / Second / Second);
into
type Netwon = Quot<Quot<Prod<Meter, Kilogram>, Second>, Second>;
but that has flaws as well, mainly due to the typechecker not doing what we want. Basically, Newton
won't always act like it's SI<P1, P1, N2>
, but instead will be treated as the associated type Output
of those computations, even though the latter, once computed, is the former. Basically, this issue.
One solution is to use a build script to generate derived types, but that doesn't help users make their own, which should be as painless as possible. Possibly this can be solved with syntax extensions, but I have no familiarity there.
The tutorial link on the front page of the docs just redirects back to the same place. I guess it is supposed to be http://paholg.com/project/dimensioned/ ?
The website link in README.md also goes to docs, when maybe it should be the project page too, but that could go either way...
Sometimes we want to sort a list of physical quantities. For such purpose, ordered_float
is useful; we want to handle with Vec<Meter<OrderedFloat<f64>>>
. However, useful constants like M
and KG
are defined only for primitive types, so there seems no really easy way to multiply quantities. Any idea how to deal with such situation? Currently I'm thinking of making a module named ordered_float_f64_consts
or something, copying entire contents of f64consts
(expanded by cargo-expand) to my project. Maybe it would be useful if this library provides a macro for defining arbitrary-type constants for existing unit system.
Thanks for this amazing project, by the way! I'm enjoying exploring the type-safety world of physical computations.
Currently, when creating a unit system, you can express what power to which you want each base unit raised. For most unit systems, this will be 1, but for example, for cgs it's 2 for the centimeters and grams.
This has some nice and some not so nice properties. Before we get to them, let me list the alternatives:
SqrtCentimeter
and SqrtGram
as the base units for cgs. Then, Centimeter
and Gram
can be easily defined as derived units.Pros and Cons:
It's intuitive to define one of these unit systems. I'm not sure how much that matters, as it would be better to just provide them in dimensioned anyway.
Printing is easy. We can use the same macro-defined Display
implementation for everything. If we switch to option 2, then the default would be to print centimeters as "sqrtcm^2" or something. But, we have a flag to not automatically implement these and could special case them, so it isn't a big deal.
Unit conversions are unintuitive. Say you want to define the conversion from cgs to mks. To do the cm -> m part, you have to do something like let cm_fac = 0.01.sqrt().powf(Centimeter.to_i32())
. The need for the sqrt
there may mess people up, whereas if the base unit is SqrtCentimeter
it may be more clear.
It increases the cognitive overhead for someone making their own unit system. Say someone wants a simple Foot, Minute
system. It'd be better for them to not have to wonder about the P1
s everywhere.
I think I've mostly convinced myself to remove this feature, but I'm open to any feedback first.
Latitude and Longitude seem to be laid out using degrees, minutes, and seconds.
https://en.wikipedia.org/wiki/ISO_6709
The closest analogous crate seems to be nav_types right now.
Not sure if you would consider this within the library scope, but I figured I'd mention it. :)
Dimensioned has terrible error messages. For example,
extern crate dimensioned as dim;
use dim::si::{M, S};
fn main() {
M + S;
}
produces the following message:
--> tests/dim-ops.rs:22:9
|
22 | M + S;
| ^ expected struct `dim::<unnamed>::PInt`, found struct `dim::<unnamed>::Z0`
|
= note: expected type `dim::si::SI<_,
dim::<unnamed>::TArr<dim::<unnamed>::PInt<dim::<unnamed>::UInt<dim::<unnamed>::UTerm, dim::<unnamed>::B1>>,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::ATerm>>>>>>>>`
= note: found type `dim::si::SI<f64,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::PInt<dim::<unnamed>::UInt<dim::<unnamed>::UTerm, dim::<unnamed>::B1>>,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::TArr<dim::<unnamed>::Z0,
dim::<unnamed>::ATerm>>>>>>>>`
where I have added line breaks to increase legibility.
I would like it to look something like this:
--> tests/dim-ops.rs:22:9
|
22 | M + S;
| ^ expected `m`, found `s`
|
= note: expected type `f64 m`
= note: found type `f64 s`
I imagine this could be accomplished by having a post-processor that creates a short Rust program which just creates variables with those type signatures and then prints them, then replaces the text.
It might only end up working for units created in dimensioned, but that's a start. It might also get hard to parse with other types mixed in there. Perhaps there's a better way?
I feel so inept at this. I appreciate the help.
I'm trying to create a helper function that will take an array slice and create a dimensioned nalgebra::Vector3
out of it... but i'm failing. This is what I've got so far:
fn dim_vector3<L, R>( unit_const :L, arr :[R ;3] ) ->
na::Vector3<dim::typenum::Prod<L, R>>
where
L: std::ops::Mul<R>
{
na::Vector3::new(
unit_const * arr[0],
unit_const * arr[1],
unit_const * arr[2]
)
}
any insight appreciated :)
Serde support (presumably behind a feature flag) would be really useful to me. I may take a stab at implementing it if I have time.
I feel that it's not necessary to serialize the unit, to save space. This means that if you changed the units of a field, it might deserialize without error. Do you think that's the right choice?
With #[rustc_on_unimplemented(mesage = "xxx", label = "xxx")]
, it is possible to customize error messages if an implementation for a trait is not found. Maybe this can produce better error messages.
It is available under #![feature(on_unimplemented)]
, which unfortunately requires nightly.
I have a function like: fn() -> Joules.
However, when I print the Joules value I get something like: 5 m^2kgs^-2
Is there an easy way to print '5 Joules' instead?
If not, what do you think a good solution to this would be? (I'm not seeing an easy way to get access to the units to compare the set of units against 'Joule' etc.)
I'd be happy to take a crack at it.
Thanks!
When I saw this on Reddit this seemed like a library that can make perfect use of my derive_more lib.
Would you be interested in a pull request to use that instead of te macros in https://github.com/paholg/dimensioned/blob/master/src/make_units.rs
There are two places in the make_units!
macro where mem::transmute
is used; for implementing Index
and IndexMut
. Both require going from &V
to &$System<V, U>
for some U
.
I think that the current use should be safe, but would like external validation. It would also be nice to replace it with something less dangerous.
If I'm not missing something, it is required only for tests, so it should be in the [dev-dependencies]
section
Even if I add a doc comment above the macro invocation, I still get a "missing documentation for a type alias" error.
Eg:
#![deny(missing_docs)]
use dimensioned::si::{self, SI};
/// Some doc comment
derived!(si, SI: InverseMeter3 = Unitless / Meter3);
We should really try moving this to typenum. Perhaps while we're at it, we may want to get away from the dimensions-tuple and use a more dynamic approach that allows us to more freely match unit types. I'm thinking about a mapping from unit to exponent, which could be implemented
(unit, exponent)
tuples, where applying a (unit, exponent)
type means a linear search for each type, though this can be quite slow as our number of units grows; merging would be in O(n²)This rust-lang/rust#28828 should have made it so the derived macro can be made better, and I think it should be in 1.17.
It would be nice to include an equivalent unit system to SI that uses imperial units.
I'm not sure what units it should use, though. For example, do we use feet for length? Inches? Miles? Furlongs?
Given that, it might make more sense that people would want to define their own with whatever units make the most sense.
I would still like to define at least one, to give a nice example of converting to and from SI, and for interoperability, so that even if someone makes their own unit system, the could define a conversion to ours to work with other crates.
For reference, SI has 7 base units: meter, kilogram, second, ampere, kelvin, candela, mole.
Dimensioned currently only works in non-stable Rust. Is it possible to disable some features when building on the stable channel, or are those features fundamentally necessary for the library implementation?
Updating registry `https://github.com/rust-lang/crates.io-index`
Downloading dimensioned v0.4.0
Downloading peano v1.0.1
Downloading num v0.1.28
Compiling peano v1.0.1
Compiling rustc-serialize v0.3.16
Compiling winapi v0.2.5
Compiling libc v0.2.2
Compiling winapi-build v0.1.1
Compiling advapi32-sys v0.1.2
Compiling rand v0.3.12
Compiling num v0.1.28
Compiling dimensioned v0.4.0
/Users/brendan/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/dimensioned-0.4.0/src/lib.rs:13:1: 13:54 error: #[feature] may not be used on the stable release channel
/Users/brendan/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/dimensioned-0.4.0/src/lib.rs:13 #![feature(optin_builtin_traits, zero_one, const_fn)]
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Users/brendan/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/dimensioned-0.4.0/src/lib.rs:14:1: 14:25 error: #[feature] may not be used on the stable release channel
/Users/brendan/.multirust/toolchains/stable/cargo/registry/src/github.com-0a35038f75765ae4/dimensioned-0.4.0/src/lib.rs:14 #![feature(type_macros)]
^~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to 2 previous errors
Could not compile `dimensioned`.
To learn more, run the command again with --verbose.
In dimensioned::unit_systems::ucum
, MH20
is a typo for MH2O
.
The repo description contains a link to http://paholg.com/dimensioned/, which seems to not exist anymore
We use a very old version of approx
, and it has been through some breaking changes since then. It would be nice to update to the new version.
Approx is used for comparing constants in tests, ensuring that converting between them gives us almost identical values.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.