Surprised that I'm the only person so far mentioning F#, where units of measure have been built in to the language since 1.0: <a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/units-of-measure" rel="nofollow noreferrer">https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...</a><p>I wrote a longer comment in reply to nraynaud elsewhere describing how I found it useful for certain things at a past job. It's hardly a killer feature, but it's very nice to have the compiler (partially) verify the semantic correctness of certain floating-point computations. It's not just physics - finance has "units" as well, and the compiler can complain if you gave a function an array of dollars/week when it wanted dollars/month.<p>If you don't mind writing some (admittedly tedious) overhead it can save a lot of headaches.
Note that this is heavily dependent on C++20. I'm not even caught up on C++17, so I was thrown off by statements like this:<p><pre><code> quantity q1 = 42 * J;
</code></pre>
where quantity is a class template:<p><pre><code> template<Reference auto R,
RepresentationOf<get_quantity_spec(R).character> Rep = double>
class quantity;
</code></pre>
I didn't know you could use auto in a template parameter. I gather that Reference is a concept, something else I've yet to explore. Just when I thought I'd gotten the hang of "modern" C++.
If you're interested in this kind of thing, I wrote a python package called "unit-syntax"(<a href="https://github.com/ahupp/unit-syntax">https://github.com/ahupp/unit-syntax</a>) that adds physical unit syntax to python:<p><pre><code> >>> speed = 5 meters/second
>>> (2 seconds) * speed
10 meter
</code></pre>
I'd been using Jupyter notebooks as a calculator for engineering problems and was wishing for the clarity and type safety of real units, but with the succinctness of regular python.<p>It works in both Jupyter notebooks (with an input transform) and stock python (with an import hook). The actual unit checks and conversions are handled by the excellent `pint` package.
All the motivating examples but one are about mixing units from different system. And of those, all but one are about errors in mixing US Customary units with the metric system. Maybe Americans should just stop using the US Customary Units as a start?
<p><pre><code> std::vector<quantity<si::milli<si::seconds>>> vec;
</code></pre>
I've seen efforts like this in the past, but in my experience there's a substantial readability cost when you replace a single-line calculation with a multi-line one to accommodate giant type definitions like this.<p>And you just <i>know</i> anyone who's adopting this library is also going to have long variable names and a strict line length limit, both of which they will describe as "clean code" :)
Scala's squants library is a nice implementation of units-of-measure/dimensional-analysis <a href="http://www.squants.com" rel="nofollow noreferrer">http://www.squants.com</a><p>In particular it uses types for <i>dimensions</i>; whilst units are just constructors. Hence `Meters(2)` and `Microns(7)` have the same type (`Length`).
I have a project for which I wrote a simple units library. I don't think I'd be able to write any physics-related project now without using it (or a similar library). My Quantity class has a set of 8 parameters (7 SI base units and a hack that allows conversion between Hz and radians) + additional Scale and Offset parameters. Scale allows representing units other than SI (like Nautical Miles), Offset is for units like Celsius, for which 0°C == 273.15 K.<p>I can do things like:<p><pre><code> si::Length length = 15_m + 12_nm; // _nm for Nautical Miles
si::Area area = 1_m * 1_km; // Equals to 1000_m2
si::Power power = 1_m / 1_sec / 1_sec; // Compilation error, 1_m/s² is not a si::Power
</code></pre>
I don't have every possible User-Defined Literal, of course, so I end up doing this for less common units:<p><pre><code> using SomeLocalTypeName = decltype(1_rpm / 1_V);
</code></pre>
Something to thing about, when designing such library:<p>* What is 0_degC + 1_degC? 1_degC or… 273.15_K + 274.15_K = 547.3_K = 274.15_degC? I forbid operations between units if any of them has Offset parameter different than 0. I'm not sure if this is the good solution, though.<p>* Nm (Newton-meters) is the same unit as Joules. ;-)
This is the one area I most sorely miss in Rust. Not that I don’t miss it anywhere else (I absolutely do, currently writing lots of TS and trying to make do with nominal types), but that it’s a very important safety mechanism in all of engineering and a unit/system of measure built into the language would fit so well.
Mateusz delivers high quality C++ code since a long time. Having implemented a similar library with C++ 03 in 2008 I highly appreciate the amount of attention to detail he invests here. We had numerous bugs in formulas found by that library over the years.
If working in python, Pint is an excellent choice: <a href="https://pypi.org/project/Pint/" rel="nofollow noreferrer">https://pypi.org/project/Pint/</a>
The manifold[1] project for Java lets you write unit expressions directly.<p>Force force = 5kg * 9.807 m/s/s;<p>1. <a href="https://github.com/manifold-systems/manifold/tree/master/manifold-deps-parent/manifold-ext#unit-expressions">https://github.com/manifold-systems/manifold/tree/master/man...</a>
Adacore developed an interesting related system for the GNAT Ada compiler: <a href="https://www.adacore.com/gems/gem-136-how-tall-is-a-kilogram" rel="nofollow noreferrer">https://www.adacore.com/gems/gem-136-how-tall-is-a-kilogram</a>
Love this! I had to implement a half-assed version of this a long time ago at a job because there was a class of subtle bugs that popped up due to poor naming/documentation/spaghetti code that would've been eliminated by things like this.
I am curious about people's experience with this kind of system, I have been thinking about it for years, but never actually tried it.<p>I sometimes feel like finding the explicit unit of some sub-expressions in geometry might be complicated. I know "auto" avoids that particular problem, but I don't have a good policy for when to put "auto" to avoid expressing a complex type and when to explicit the type to block the propagation of errors.<p>Also during debugging we might need to display some customary unit for sub expressions/watchpoints because the SI unit means nothing to humans in some fields (pressure comes to mind, some people use mm of water, mm of mercury, bars, etc.)
> Although it makes physical sense to add heights of daily climbs, there is no sense in adding altitudes.<p>What if I want to compute the average altitude? This requires adding altitudes.
While this is a nice thing to have I dread the day that codes start to require people get with this. Yes, it's a source of bugs, sometimes people need to accept that bugs naturally arise because of something called the undecideability and we need to stop shoehorning things into languages to make things safe. It makes sense in a host of features but the problem with these sorts of features is they make a lot of a assumptions, including the fact that codes with units will actually be better with units.