Got a weird situation I think might be a bug. Not sure. But I have this:
class Y {
has Int $.vol;
has Str $.quant;
has Str $.abbr;
submethod BUILD(
Str :$!abbr,
Int :$!vol,
) { }
}
class X is Y {
multi method new(Int:D :$vol) {
self.bless(
:$vol,
:abbr('C'),
);
}
multi method new(Str:D :$quant) {
self.bless(
:$quant,
:abbr('C'),
);
}
}
my $x = X.new(vol => 7);
say $x;
# OUTPUT: X.new(vol => 7, abbr => "C")
This works as expected. The abbr
attribute is populated. However, in the code below, I can't get the abbr
to populate:
#!/usr/bin/env raku
use v6.d;
use Lingua::EN::Numbers;
constant Nᴀ = 602214076000000000000000;
class Mass-t { ... }
class Mass-kg { ... }
class Mass-g { ... }
class Mass-mg { ... }
class Mass-ug { ... }
class Mass-mcg { ... }
class Mass-oz { ... }
class Mass-lb { ... }
class Mass-c { ... }
class Volume-m { ... }
class Volume-cm { ... }
class Volume-mm { ... }
class Length-cm { ... }
class Length-m { ... }
class Length-mm { ... }
class Quantity-mol { ... }
class Quantity-dz { ... }
class Substance-c { ... }
class Substance-air { ... }
class Volume { ... }
END {
my $v = Quantity-mol.new(1.0);
my $c = Substance-c.new(quant => $v);
say $c;
say 'done with program';
exit;
}
class Quantity {
has Str $.name;
has Str $.abbr is rw;
has Rat $.value;
has Rat $.base_value;
submethod BUILD(Rat :$!value,
Str :$!name,
Str :$!abbr,
Rat :$!base_value,
) { }
method get_value() {
return $!value ~ ' ' ~ $!abbr;
}
method count(Bool:D $comma = True) {
return comma $!value * $!base_value if $comma;
return $!value * $!base_value;
}
method to(Str:D $abbr-in) {
my $class = split('-', self.^name)[0];
my $abbr = $abbr-in.lc;
my $to = ::("$class-$abbr").new();
self!convert($to);
}
method !convert(Quantity:D $to) {
my $result = comma (self.count(False) / $to.base_value);
return $result ~ ' ' ~ $to.abbr;
}
}
class Quantity-mol is Quantity {
method new(Rat:D() $value = 1.0) {
self.bless(
:name('mole'),
:abbr('㏖'),
:base_value(Rat.new(Nᴀ, 1)),
:$value,
);
}
}
class Quantity-dz is Quantity {
method new(Rat:D() $value = 1.0) {
self.bless(
:base_value(12.0),
:name('dozen'),
:abbr('dz'),
:$value,
);
}
}
class Measure {
has Str $!name;
has Str $.abbr is rw;
has Rat $.value;
has Rat $.base_value;
has Rat $.imp_base_value;
submethod BUILD(Rat :$!value,
Str :$!name,
Str :$!abbr,
Rat :$!base_value,
Rat :$!imp_base_value,
) { }
method to(Str:D $abbr-in) {
my $class = split('-', self.^name)[0];
my $abbr = $abbr-in.lc;
my $to = ::("$class-$abbr").new();
self!convert($to)
}
method !convert(Measure:D $to) {
my $imp_conv = $.imp_base_value && $to.imp_base_value;
my $base_value = $imp_conv ?? $.imp_base_value !! $.base_value;
my $to_base_value = $imp_conv ?? $to.imp_base_value !! $to.base_value;
my $conversion = ($.value * $base_value) / $to_base_value;
my $num = $conversion > 1 ?? comma ($conversion) !! $conversion < 1/10000 ?? (sprintf "%.5e", $conversion) !! $conversion;
# do pretty scientific notation
if $conversion < 1 / 10000 {
my $exp = $num ~~ / '-' 0* <(\d+)>$/;
$exp .= trans( '0123456789' => '⁰¹²³⁴⁵⁶⁷⁸⁹' );
$num .= subst(/e\-\d+/, "\x[00D7]10\x[207B]$exp");
}
return $num ~ ' ' ~ $to.abbr;
}
method !count {
}
}
class Mass is Measure { }
class Length is Measure { }
class Substance {
has Quantity-mol $.quant;
has Volume $.vol;
has Str $.abbr is rw;
submethod BUILD(Quantity-mol :$!quant,
Volume :$!vol,
Str :$!abbr,
) { }
method volume() {
return $.vol.value ~ ' ' ~ $.vol.abbr;
}
method moles() {
return $.quant.value ~ ' ' ~ $.quant.abbr ~ ' ' ~ $.abbr;
}
}
class Substance-co2 is Substance {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('cm'),
:$value,
);
}
}
class Substance-c is Substance {
multi method new(Volume:D $vol) {
self.bless(
:$vol,
:abbr('C'),
);
}
multi method new(Quantity-mol:D $quant) {
self.bless(
:$quant,
:abbr('C'),
);
}
}
class Substance-air is Substance {
}
class Length-cm is Length {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('cm'),
:base_value(1/100),
:$value,
);
}
}
class Length-m is Length {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('m'),
:base_value(1.0),
:$value,
);
}
}
class Length-mm is Length {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('mm'),
:base_value(1/1000),
:$value,
);
}
}
class Volume is Measure {
has Str $.abbr;
has Rat $.base_value;
has Rat $.value;
}
class Volume-m is Volume {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('m³'),
:base_value(1.0),
:$value,
);
}
}
class Volume-cm is Volume {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('cm³'),
:base_value(1 / 1_000_000),
:$value,
);
}
}
class Volume-l is Volume {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('l'),
:base_value(1 / 1_000),
:$value,
);
}
}
class Volume-ml is Volume {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('ml'),
:base_value(1 / 1_000_000),
:$value,
);
}
}
class Volume-mm is Volume {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('mm³'),
:base_value(1 / 1_000_000_000),
:$value,
);
}
}
class Density {
has Mass $.mass;
has Volume $.volume;
method calculate() {
return $.mass / $.volume;
}
}
class Density-water {
method new(Rat:D()) {
self.bless(
:mass(Mass-kg.new()),
:volume(Volume-l.new()),
);
}
}
class Mass-c is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('g/mol'),
:base_value(12.0107),
:$value,
);
}
}
class Mass-air is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('g/mol'),
:base_value(28.9647),
:$value,
);
}
}
class Mass-Da is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('Da'),
:base_value(Rat.new(1, 602214075789225073400000)),
:$value,
);
}
}
class Mass-kg is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('kg'),
:base_value(1000.0),
:$value,
);
}
}
class Mass-oz is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('oz'),
:base_value(28.3495231),
:imp_base_value(1/16),
:$value,
);
}
}
class Mass-lb is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('lb'),
:base_value(453.59237),
:imp_base_value(1.0),
:$value,
);
}
}
# lb aliases
class Mass-g is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('g'),
:base_value(1.0),
:$value,
);
}
}
class Mass-mg is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('mg'),
:base_value(1/1000),
:$value,
);
}
}
class Mass-ug is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('µg'),
:base_value(1/1_000_000),
:$value,
);
}
}
class Mass-mcg is Mass-ug {
method TWEAK { $.abbr = "mcg" }
}
class Mass-mt is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('mt'),
:base_value(1_000_000.0),
:$value,
);
}
}
class Mass-gt is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('mt'),
:base_value(1_000_000_000_000.0),
:$value,
);
}
}
class Mass-t is Mass {
method new(Rat:D() $value = 1.0) {
self.bless(
:abbr('t'),
:base_value(907184.74),
:$value,
);
}
}
This outputs:
Substance-c.new(quant => Quantity-mol.new(name => "mole", abbr => "㏖", value => 1.0, base_value => 602214076000000000000000.0), vol => Volume, abbr => Str)
Note here the abbr
attribute never gets set. It's just says Str
(be sure to scroll all the way to the right to see this). I've been staring at this for a long time and cannot figure it out what's going on.