[GSoC Proposal] Statically Checked Measurement Units

David Nadlinger see at klickverbot.at
Tue Mar 29 14:40:52 PDT 2011


On 3/29/11 3:49 PM, Cristi Cobzarenco wrote:
> To David:
> Ok, right now, I got two working versions, one sorting by .mangleof and
> one performing a double-inclusion test on the tuples. Both work, I can't
> see any performance increase in the .mangleof one, but if .mangleof
> returns unique string, I say we use it this way.

To be honest, I still don't see how you are able to get away without 
canonicalization in the first place; would you mind to elaborate on how 
you solve the issue of different ordering of expression yielding types? 
This is not about the algorithm to determine whether two types are 
semantically equivalent, where your algorithm would work fine as well, 
but about the actual D types. If you don't sort them, 
Quantity!(BaseUnitExp!(Meter, 1), BaseUnitExp!(Second, -2)) and 
Quantity!(BaseUnitExp!(Second, -2), BaseUnitExp!(Meter, 1)) would be 
different types, which is not desirable for obvious reasons.


> Regarding my string little DSL. I have 3 solutions right now:
> 1. Drop the DSL altogether, right now my system would work perfectly
> fine with boost-like tuples (a list of units alternating with exponents):
> Quantity!(Metre,1,Second,-1) speed = distance/time;
> While less readable, this doesn't have the disadvantages of the following 2.
>
> 2. Use a mixin template to declare the expression parser in the current
> scope:
> mixin DeclareExprQuantity!();
>
> struct Metre {}
> struct Second {}
> struct Kg {}
>
> void f() {
>         ExprQuantity!("Metre/Second * Kg^-1") q = speed / mass;
> }
> This works, is readable, but it uses C-preprocessor like behaviour
> (read: black vodoo) - a library declaring something in your scope isn't
> very nice.
>
> […]
>
> The only completely clean alternative would be the abominable:
> Quantity!( mixin(Expr!("Metre/Second")) ) q;

Get out of my head! Immediately! ;) Just kidding – incidentally I 
considered exactly the same options when designing my current prototype. 
My current approach would be a mix between 1 and 2: I don't think the 
Boost approach of using »dummy« instances of units is any less readable 
than your proposed one when you don't deal with a lot of units. For 
example, consider

enum widgetCount = quantity!("Widget")(2);
vs.
enum widgetCount = 2 * widgets;

This could also be extended to type definitions to avoid having to 
manually write the template instantiation:

Quantity!("meter / second", float) speed;
vs.
typeof(1.f * meter / second) speed;

There are situations, though, where using unit strings could 
considerable improve readability, namely when using lots of units with 
exponents. In these cases, a mixin could be used to bring all the types 
in scope for the »parsing template«, similar to the one you suggested. 
If a user of the library things  could use an additional mixin 
identifier to clarify the code, e.g. »mixin UnitStringParser U; […] 
U.unit!"m/s"«).

But a more attractive solution would exploit the fact that you would 
mostly use units with a lot of exponents when working with a »closed« 
unit system without the need for ad-hoc extensions, like the SI system, 
which would allow you to use unit symbols instead of the full name, 
which wouldn't need to be globally unique and wouldn't pollute the 
namespace (directly defining a type »m« to express meters would probably 
render the module unusable without static imports).

It would essentially work by instantiating a parser template with all 
the named units. Thus, the parser would know all the types and could 
query them for additional properties like short names/symbols, etc. In code:

---
module units.si;
[…]
alias UnitSystem!(Meter, Second, …) Si;
---
module client;
import units.si;
auto inductance = 5.0 * Si.u!"m^2 kg/(s^2 A^2)";
---

This could also be combined with the mixin parser approach like this:
---
import units.si;
mixin UnitStringParser!(Si) U;
---

But to reiterate my point, I don't think a way to parse unit strings is 
terribly important, at least not if it isn't coupled with other things 
like the ability to add shorthand symbols.

David


More information about the Digitalmars-d mailing list