First, let me apologize for this very late entry, it's the end of university and it's been a very busy period, I hope you will still consider it.
Note this email is best read using a fixed font. PS: I'm really sorry if this is the wrong mailing list to post and I hope you'll forgive me if that's the case. ======= Google Summer of Code Proposal: Statically Checked Units ======= Abstract ------------- Measurement units allow to statically check the correctness of assignments and expressions at virtually no performance cost and very little extra effort. When it comes to physics the advantages are obvious – if you try to assign a force a variable measuring distance, you've most certainly got a formula wrong somewhere along the way. Also, showing a sensor measurement in gallons on a litre display that keeps track of the remaining fuel of a plane (a big no-no) is easily avoidable with this technique. What this translates is that one more of the many hidden assumptions in source code is made visible: units naturally complement other contract checking techniques, like assertions, invariants and the like. After all the unit that a value is measured in is part of the contract. The scope of measurement units is not limited to physics calculations however and if the feature is properly implemented and is very easy to use, creating a very domain-specific units helps a great deal with checking correct code at compile time. Static typing doesn't cut it sometimes: imagine two variables counting different things – Gadgets and Widgets. While both values should be ints, one of them should probably not be assignable to the other. Or imagine a website calculating the number of downloads per second, but uses a timer that counts milliseconds. When one thinks about it this way, there are a great many cases where units can help prevent common errors. Given D's focus on contract based design and language features supporting it, I think statically checked measurement units fit very naturally into the standard library, and the language's metaprogramming features would make it very clean to implement (as opposed to a similar effort in C++). I think a system that is closer to the one in F# would be a better idea than the one provided by Boost.Units: 1. Defining unit systems, like Boost.Units requires is extra effort, so units for counting Widgets or Gadgets would be awkward to use and we would lose the safety checks there. 2. Defining dimensions is not strictly necessary, and F# does well without them. 3. The sort of silent conversion that Boost.Units performs is undesirable in many cases since it is a recipe for precision disasters, imagine sometimes accidentally assigning a variable measured in billions of years to a one measured in picoseconds. Boost.Units would silently convert one to another, since they measure the same dimension. This probably results into the value being set to +INF and even if it doesn't, very rarely one actually intends to perform this conversion. 4. Setting numerical ids to units and dimensions is cumbersome. S Thus, the requirements for the unit system would be: 1. One line definition of new units. 2. Simple, yet safe and explicit conversion between units. 3. Zero runtime overhead. 4. Minimal extra coding effort to use units. Interface Overview --------------------------- A Boost type approach to the library interface would be: struct Metre : SomeUnitBaseType!(...) {} struct Second : SomeUnitBaseType!(...) {} typedef DerivedUnit!(MetreType,1,Second,-1) MetresPerSecond; typedef DerivedUnit!(MetreType,2) MetersSquared; Meter metre, metres; Second second, seconds; MetersPerSecond metersPerSecond; MetersSquared meterSquared, metersSquared; void f() { Quantity!(metre) dist1 = 3.0 * metres; Quantity!(meterSquared) area = dist1 * dist1; Quantity!(metresPerSecond) speed = distance / (2.0*seconds); } This is very cumbersome and fails on the one line requirement. I propose using types for base units and mixins to define derived units. One can use the typenames of the units in arithmetic operations this way: struct metre {} struct second {} void f() { Quantity!("metre") dist1 = quantity!(3.0, "metre"); Quantity!("metre^2") area = dist1 * dist1; Quantity!("metre/second") speed = dist1 / quantity!(2.0, "second"); } Conversion between units can be done specifying a single factor with a proper unit: template conversion( alias unit : "kilometer/meter" ) { immutable Quantity!(unit) conversion = quantity!(123.0,unit); } void f() { Quantity!("metre") d1 = quantity!(123.0,"metre"); // convert calls conversion! with the right argument Quantity!("kilometre") d2 = convert!(d1,"kilometre"); } Also, notice this approach imposes no restriction to the types that define units, therefore our Widget/Gadget counters could be defined without any extra work: class Widget { /* complicated class definition */ } class Gadget { /* complicated class definition */ } Quantity!("Widget",int) nWidgets; Quantity!("Gadget",int) nGadgets; About Me ------------ I am an undergraduate student at the University of Edinburgh in Scotland doing a degree in Computer Science and Artificial Intelligence, originally from Romania where I finished a specialised Computer Science high school (Colegiul National de Informatica "Tudor Vianu"). My first language is C++ which I started learning when I was 9 and as a result I have a very good understanding of template metaprogramming. I also know Haskell and Python well which helps me draw from multiple paradigms when designing as system. I started learning D about a year ago and I instantly fell in love with it. The fact that it does away with all the annoying C backwards compatibility, improves on the features that make C++ unique (the template system, performance, low level memory access etc.) and adds modern language features (garbage collection, lambda functions etc.) makes me very optimistic about the project. In terms of working experience, other than a myriad of personal projects, I did work for my former high school for a summer, implementing an automated testing system, and last year I was lead a team that won a software development competition organised by our computing society. This year I took part in the Scottish Game Jam where my team ended up in 8th place. -- (Cristi Cobzarenco) Pofile: http://www.google.com/profiles/cristi.cobzarenco