[GSoC Proposal] Statically Checked Measurement Units

Cristi Cobzarenco cristi.cobzarenco at gmail.com
Tue Mar 29 06:49:33 PDT 2011


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.
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.

3. Abandon using types as units and just use strings all the way. This
doesn't guarantee unit name uniqueness and a misspelled unit name is a new
unit. One could use an algorithm to convert all strings to a cannonical form
(like Andrei suggested) and then use string equality for unit equality.

What do you think, I'm personally quite divided:
1. I like that this is simple and it works. It make writing derived units
unnatural though.
2. I actually like this one, despite the obvious ugliness. It's just one
extra line at the beginning of your code and you can the use arithmetic
operations and use type-uniqueness to guarantee unit-uniqueness.
3. This is a bit dangerous. It works very well as long as there isn't more
than one system of units. I still like it a bit.

The only completely clean alternative would be the abominable:
Quantity!( mixin(Expr!("Metre/Second")) ) q;



To Don:
* Choosing one unit and using it is still a very good idea. As I said there
are to be no implicit conversions, so this system would ensure you don't, by
mistake, adhere to this convention. Also, if somebody else uses your library
maybe they assume everything is in meters when in fact you use milimeters.
Sure they should check the documentation, but it's better if they get a nice
error message "Inferred unit Meter doesn't match expected Milimeter", or
something like that.
* True, scale errors can be figured out easily, multiplying something with
an acceleration instead of velocity, or forgetting to multiply acceleration
by a timestep isn't as easily checked. Multiplying instead of dividing in a
formula, or forgetting to divide by a normalisation constant are other
things you may forget, and are caught instantly by unit checking.
* Arrays & vectors are very important, I agree. The Quantity! type is
parametrised both by a unit and a value type, therefore, if one wants a
vector whose components are of the same unit, using "Quantity!(Metre,
Vector!(double))" would work. Vector!(Quantity!(Metre,double)) would also
work. As long as the value type has arithmetic operations defined everything
works out. Same goes for arrays.

There is a risk that it never gets used, sure. But I think that units will
become commonplace, some time in the future, so while it won't get wide
acceptance very soon, at some point people will be looking on Wikipedia for
"Languages supporting measurement units" and it will be good for D to show
up there.




On 29 March 2011 14:36, Don <nospam at nospam.com> wrote:

> Cristi Cobzarenco wrote:
>
>> To Don:
>> That is a very good point and I agree that one shouldn't implement
>> features just because they're popular. There don't seem to be many (if any
>> projects) using Boost.Units and only a few that use the feature in F#.
>> But, I think the reason Boost.Units isn't use hasn't got much to do with
>> the idea as much as it does with the implementation. Using units in Boost is
>> very cumbersome. Adding new units (measuring different dimensions)
>> on-the-fly is virtually impossible. I think that that Boost.Units misses the
>> point of units. They should be a natural extension of the type system of a
>> language, not something so limited to the area of natural sciences. D is a
>> new language and we should be pushing the envelope, just because the Boost
>> failed (if it did, it may very well kick-off later) doesn't mean we
>> shouldn't do it. Since it is such a new feature, I think we should talk
>> about its potential rather than its acceptance.
>> When it comes to F#, I think the reason there aren't many projects using
>> units is because there aren't many projects in F# period. It is a very
>> popular feature in the F# community (judging by blog posts and the like) and
>> people are still trying to figure out exactly how to use it. I feel that in
>> F#, it has the potential to become very widely used once people agree on
>> some conventions and good practices.
>> As I said in the abstract, I think the feature fits snugly with other
>> mechanisms in D and seems to be a natural part of a contract-based design,
>> so D programmers should have a predisposition (that C++ programmers might
>> not have) of adopting such a feature.
>>
>> I really hope this doesn't come off as rude; as I said, you make a very
>> good point, one that needs answering. I guess what I'm saying can be summed
>> up as: it is a new feature; there have been mistakes; it has a lot of
>> potential and we can make it better. I'd be curious to hear what you think.
>>
>
> I'm a physicist and most of my programming involves quantities which have
> units. Yet, I can't really imagine myself using a units library. A few
> observations from my own code:
> * For each dimension, choose a unit, and use it throughout the code. For
> example, my code always uses mm because it's a natural size for the work I
> do. Mixing (say) cm and m is always a design mistake. Scaling should happen
> only at input and output, not in internal calculations. (So my feeling is,
> that the value of a units library would come from keeping track of dimension
> rather than scale).
> * Most errors involving units can, in my experience, easily be flushed out
> with a couple of unit tests. This is particularly true of scale errors. The
> important use cases would be situations where that isn't true.
> * Arrays are very important. Although an example may have force = mass *
> accelaration, in real code mass won't be a double, it'll be an array of
> doubles.
>
>
> > Since it is
> > such a new feature, I think we should talk about its potential rather
> > than its acceptance.
>
> I'm really glad you've said that. It's important to be clear that doing a
> perfect job on this project does not necessarily mean that we end up with a
> widely used library. You might be right that the implementations have held
> back widespread use -- I just see a significant risk that we end up with an
> elegant, well written library that never gets used.
> If the author is aware of that risk, it's OK. If not, it would be a very
> depressing thing to discover after the project was completed.
>
>


-- 
(Cristi Cobzarenco)
Pofile: http://www.google.com/profiles/cristi.cobzarenco
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20110329/376660c9/attachment.html>


More information about the Digitalmars-d mailing list