Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can one perl6 module conditionally 'use' another perl6 module?

Tags:

Is there a sensible way to have one perl6 module check for the presence of another perl6 module and to 'use' it if and only if it is installed?

Something like this...

module Polygons;

if $available {
    use Measure;                #only if Measure is installed
}

class Rectangle is export {
    has $.width;
    has $.height;

    method area {
        $!width * $!height;     #provides operator overload for Measure * Measure
    }
}
#====================

module Measure;

class Measure is export {
    has $.value;
    has $.unit;

    method Real {
        $!value;
    }
    method Str {
        "$!value $!unit";
    }
    method multiply( $argument ) {
        my $result = $.;
        $result.value = $!value * $argument;
        $result.unit  = "$!unit2";
        return $result;
    }
}

multi infix:<*> ( Measure:D $left, Measure:D $right ) is export {
    return $result.multiply( $argument );
}

#====================

#main.p6

use Polygons;
use Measure;

my $x = Measure.new( value => 10, unit => 'm' );
my $y = Measure.new( value => 20, unit => 'm' );

my $rect = Rectangle.new( width => $x, height => y );
say $rect.area;        #'200 m2'

The idea is to propagate the operator overload (infix:<*> in this case) back up the class inheritance so that one store more elaborate objects in the attributes.

(Without tearing up the drains please - since I suspect there is always a way!)

like image 230
p6steve Avatar asked Jan 06 '19 17:01

p6steve


1 Answers

So the first version of this answer was essentially useless.

Here's the first new thing I've come up with that works with what I understand your problem to be. I haven't tried it on the repo yet.

In a file a-module.pm6:

unit module a-module;
our sub infix:<*> ($l,$r) { $l + $r } }

The our means we'll be able to see this routine if we can require it, though it'll only be visible via its fully qualified name &a-module::infix:<*>.

Then in a using file:

use lib '.';
try require a-module;
my &infix:<*> = &a-module::infix:<*> // &OUTER::infix:<*>;
say 1 * 2 # 2 or 3 depending on whether `a-module.pm6` is found

The default routine used if the module is missing can be the one from OUTER (as shown) or from CALLER or whatever other pseudo package you prefer.

This problem/solution seems so basic I suspect it must be on SO or in the doc somewhere. I'll publish what I've got then explore more tomorrow.

like image 160
raiph Avatar answered Dec 12 '22 04:12

raiph