On 03/28/2011 05:43 PM, Cristi Cobzarenco wrote:
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.
I like your study very much. Measurement units are, for me, kinds of conceptual
types --as opposed to primitive types. I think they would be welcome, possibly
for Phobos.
[...]
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");
}
I think (not sure) this could be even simpler:
1. Thank to D's very used auto feature, avoiding double specification of the
type; you could get rif of quantity, if it's only a convenience factory func.
2. I guess it's not needed for the user to give a quantity type to
/constants/ (here 2.0). It is /meant/ to be a a number of seconds. This, as
opposed to measure /variables/.
Thus, we possibly could have:
auto dist1 = Quantity!("meter")(3.0);
auto area = Quantity!("metre^2")(dist1 * dist1);
auto speed = Quantity!("metre/second")(dist1 / 2.0);
(Unsure whether your system could automagically infer the unit of area. ?)
I'm not fan of using strings as unit identifiers. Why don't you want to use use
the corresponding types (structs or classes) themselves?
auto dist1 = Quantity!Meter(3.0);
Thus requiring each unit to be identified by a (possibly empty) struct or
class. This also gives the opportunity for the user to actually implement some
useful stuff in there; or to *reuse* existing types for things-to-be-counted
(in the latter case, measures would actually be integer /counts/); see your
Widget vs Gadget example below).
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);
}
Unsure of the right approch here. All we need is a registered conversion factor
for every needed (U1,U2) pair. It could be a kind of 2D associative array with
unit keys and float values. Then, would it be possible to have a single convert
template, like:
Quantity!U2 convert (string U1, string U2) (Quantity!U1 measure) {
auto factor = conversionFactors[U1][U2]; // throws if undefined
return Quantity!U2(measure * factor);
}
?
void f() {
Quantity!("metre") d1 = quantity!(123.0,"metre");
// convert calls conversion! with the right argument
Quantity!("kilometre") d2 = convert!(d1,"kilometre");
}
auto d1 = Quantity!("metre")(123.0);
auto d2 = convert!(d1,"kilometre");
or using my approach:
auto d2 = convert!("metre","kilometre")(d1);
Here the type for d2 is really unnecessary.
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;
See note about identifying units above.
Denis
--
_________________
vita es estrany
spir.wikidot.com