Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@ahalbert
Created May 10, 2016 03:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ahalbert/f7c56de80d3266c56ceb1f7105de3651 to your computer and use it in GitHub Desktop.
Save ahalbert/f7c56de80d3266c56ceb1f7105de3651 to your computer and use it in GitHub Desktop.
use v6;
unit module Units;
class Unit {
has Rat $.magnitude;
has %.units;
multi method mergeUnits(Unit $u) {
my %unitm = $u.units;
my $op = &[+];
for keys %!units -> $unit {
if (%!units{$unit}:exists) { %!units{$unit} = $op(%!units{$unit}, %unitm{$unit}); }
else {%!units{$unit} = %unitm{$unit};}
}
return self.cleanUnits();
}
method cleanUnits() {
for keys %!units -> $unit {
if (%!units{$unit} == 0) {%!units{$unit}:delete;}
}
}
method isSameUnit(Unit $comp) {
my %u = $comp.units;
if (not %!units == %u) {
return False;
}
for keys %!units -> $u {
if (%!units{$u} != %u{$u}) {return False;}
}
return True;
}
method gist {
my $unitString = "";
my $negUnitString = "";
for kv %!units -> $unit, $exp {
if ($exp > 0) {$unitString = $unitString ~ $unit ~ "^" ~ $exp ~ "*";}
else {$negUnitString = $unitString ~ $unit ~ "^" ~ (abs $exp) ~ "*";}
}
$unitString = ($!magnitude.gist) ~ " " ~ $unitString.chop;
if ($negUnitString === "") {return $unitString;}
return $unitString ~ "/" ~ $negUnitString.chop;
}
}
multi sub infix:<==> (Units::Unit $x, Units::Unit $y) is export {
if (not $x.isSameUnit($y)) {die "Units do not match.";}
return $x.magnitude == $y.magnitude;
}
multi sub infix:<===> (Units::Unit $x, Units::Unit $y) is export {
return $x.isSameUnit($y) && ($x.magnitude == $y.magnitude);
}
multi sub infix:<+>(Units::Unit $x, Units::Unit $y) is export {
if (not $x.isSameUnit($y)) {die "Units do not match.";}
return Unit.new(magnitude => $x.magnitude + $y.magnitude, units => $x.units);
}
multi sub infix:<->(Units::Unit $x, Units::Unit $y) is export {
if (not $x.isSameUnit($y)) {die "Units do not match.";}
return Unit.new(magnitude => $x.magnitude - $y.magnitude, units => $x.units);
}
multi sub infix:<*>(Units::Unit $x, Units::Unit $y) is export {
return Unit.new(magnitude => $x.magnitude * $y.magnitude, units => $x.mergeUnits($y.units));
}
multi sub infix:</>(Units::Unit $x, Units::Unit $y) is export {
return Unit.new(magnitude => $x.magnitude / $y.magnitude, units => $x.mergeUnits(&[-], $y));
}
my $a = Units::Unit.new(magnitude => 1.2, units => ("m" => 1));
my $b = Units::Unit.new(magnitude => 5.0, units => ("m" => 1));
my $c = Units::Unit.new(magnitude => 5.0, units => ("m" => 1, "s" => -1));
say $a * $b;
# ERROR:
# Cannot call AUTOGEN(Units::Unit: Hash); none of these signatures match:
# (Units::Unit $: Units::Unit $u, *%_)
# Cannot call mergeUnits(Units::Unit: Hash); none of these signatures match:
# (Units::Unit $: Units::Unit $u, *%_)
# in sub infix:<*> at lib/math/units.pm6 line 65
# in block <unit> at lib/math/units.pm6 line 78
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment