Skip to content

Instantly share code, notes, and snippets.

@jasononeil jasononeil/Metric.hx
Last active Nov 10, 2016

Embed
What would you like to do?
Demonstration of using Haxe abstracts to take care of explicit conversions between different units of measurement, with no performance overhead.
class Metric {
static function main() {
var coinRadius:Millimeters = 12;
var myHeight:Centimeters = 180;
var raceLength:Meters = 200;
var commuteDistance:Kilometers = 23;
diff( coinRadius, myHeight ); // 1.788 meters
diff( raceLength, commuteDistance ); // 22800 meters
sum( commuteDistance, coinRadius ); // 23000.012 meters
}
static function diff( a:Meters, b:Meters ) {
var d = Math.abs( a-b );
trace( '$d meters' );
}
static function sum( a:Meters, b:Meters ) {
var s = Math.abs( a+b );
trace( '$s meters' );
}
}
abstract Millimeters( Float ) from Float to Float {
@:to function toCentimeters():Centimeters return this/10;
@:to function toMeters():Meters return this/1000;
@:to function toKilometers():Kilometers return this/1000000;
@:op(A+B) function add(rhs:Float):Float return this+rhs;
@:op(A-B) function sub(rhs:Float):Float return this-rhs;
@:op(A-B) function multiply(rhs:Float):Float return this*rhs;
@:op(A-B) function divide(rhs:Float):Float return this/rhs;
}
abstract Centimeters(Float) from Float to Float {
@:to function toMillimeters():Millimeters return this*10;
@:to function toMeters():Meters return this/100;
@:to function toKilometers():Kilometers return this/100000;
@:op(A+B) function add(rhs:Float):Float return this+rhs;
@:op(A-B) function sub(rhs:Float):Float return this-rhs;
@:op(A-B) function multiply(rhs:Float):Float return this*rhs;
@:op(A-B) function divide(rhs:Float):Float return this/rhs;
}
abstract Meters( Float ) from Float to Float {
@:to function toMillimeters():Millimeters return this*1000;
@:to function toCentimeters():Centimeters return this*100;
@:to function toKilometers():Kilometers return this/1000;
@:op(A+B) function add(rhs:Float):Float return this+rhs;
@:op(A-B) function sub(rhs:Float):Float return this-rhs;
@:op(A-B) function multiply(rhs:Float):Float return this*rhs;
@:op(A-B) function divide(rhs:Float):Float return this/rhs;
}
abstract Kilometers( Float ) from Float to Float {
@:to function toMillimeters():Millimeters return this*1000000;
@:to function toCentimeters():Centimeters return this*100000;
@:to function toMeters():Meters return this*1000;
@:op(A+B) function add(rhs:Float):Float return this+rhs;
@:op(A-B) function sub(rhs:Float):Float return this-rhs;
@:op(A-B) function multiply(rhs:Float):Float return this*rhs;
@:op(A-B) function divide(rhs:Float):Float return this/rhs;
}
(function () { "use strict";
var Metric = function() { };
Metric.main = function() {
var coinRadius = 12;
var myHeight = 180;
var raceLength = 200;
var commuteDistance = 23;
Metric.diff(coinRadius / 1000,myHeight / 100);
Metric.diff(raceLength,commuteDistance * 1000);
Metric.sum(commuteDistance * 1000,coinRadius / 1000);
};
Metric.diff = function(a,b) {
var d = Math.abs(a - b);
console.log("" + d + " meters");
};
Metric.sum = function(a,b) {
var s = Math.abs(a + b);
console.log("" + s + " meters");
};
Metric.main();
})();
@jasononeil

This comment has been minimized.

Copy link
Owner Author

jasononeil commented Aug 25, 2014

I wrote this as an example for a Hacker News comment - it shows how "Abstract Types" in Haxe can be used to deal with units of measurement, providing inline, implicit conversion and keeping you from getting your units mixed up.

The best part is, it wraps an ordinary Float, and when you compile, that's all it is. Take a look at how clean the Javascript output is.

It would be great to see a more comprehensive library that deals with many units of measurement (distance, volume, time, speed and more) and provides clean conversion between them.

@larsiusprime

This comment has been minimized.

Copy link

larsiusprime commented Aug 25, 2014

Should this line: https://gist.github.com/jasononeil/b6b1845824f45f5d19df#file-metric-hx-L40

@:op(A-B) function multiply(rhs:Float):Float return this*rhs;

instead be:

@:op(A*B) function multiply(rhs:Float):Float return this*rhs;

Or am I missing something?

@ibilon

This comment has been minimized.

Copy link

ibilon commented Aug 26, 2014

@larsiusprime I think so too, same for @:op(A/B) function divide(rhs:Float):Float return this/rhs;

@jasononeil I've started working on one: https://github.com/ibilon/units

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.