Possible to create class aliases dynamically?

Viewed 92

Got this class:

class Mass-lb is Mass {
    method new(Rat:D() $value = 1.0) {
        self.bless(
            :abbr('lb'),
            :base_value(453.59237),
            :$value,
        );
    }
}

I have created aliases like this:

class Mass-lbs is Mass-lb { }
class Mass-pound is Mass-lb { }
class Mass-pounds is Mass-lb { }
class Mass-pnds is Mass-lb { }

But I'd prefer to do something like this:

my @lb-syn = < lbs pounds pound pnds >;
for @lb-syn {
    EVAL 'class ::("Mass-$_") is Mass-lb {}';
}

This throws an error:

Name ::("Mass-$_") is not compile-time known, and can not serve as a package name

PHP has a built-in for creating aliases: https://www.php.net/manual/en/function.class-alias.php

I couldn't find anything similar for raku.

2 Answers

In RakuAST there's a class that you can call to create a new type. But that the RakuAST branch hasn't landed yet.

Until then, your approach using EVAL is valid, you just need to make it a bit simpler:

class Mass-lb { }
BEGIN "constant Mass-$_ = Mass-lb".EVAL
  for <lbs pounds pound pnds>;
my $mlb = Mass-lbs.new;
  1. Make sure the aliases are created at BEGIN time.
  2. No need to subclass, you can use a constant for aliasing.
  3. Since constants are our by default, they're visible outside of the EVAL.

Alternatively, you could use raku Physics::Unit and Physics::Measure...

use Physics::Unit;
use Physics::Measure :ALL;

# define a new custom Unit
Unit.new( defn => 'lbm', names => <Mass-lb Mass-lbs Mass-pound Mass-pounds Mass-pnds> );

say GetUnit('Mass-lbs').names;      #[Mass-lb Mass-lbs Mass-pound Mass-pounds Mass-pnds]

# use the Unit in a Measure 
my $mass = ♎️'42 Mass-pnds';
say $mass;                          #42Mass-lb
say $mass.^name;                    #(..Mass) ...class name

# convert to another Unit
my $kgm = $mass.in: 'kg';
say $kgm;                           #19.05087954kg

# convert back 
say $kgm.in: 'Mass-pound';          #42Mass-lb

# raku Rats mean that the back conversion is identical
say $kgm cmp $mass;                 #Same

# with % or abs Error
my $mass2 = ♎️'42 Mass-pnds ±3%';
say $mass2;                         #42Mass-lb ±1.26
say $mass2.in: 'kg';                #19.05087954kg ±0.5715263862

More info at github Physics::Unit and Physics::Measure...

Related