[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