Clone Wars

Apologies to those that have OO steeped in their blood. I am a wary traveller in OO space,  maybe I am an technician, not an architect at heart. So for me, no sweeping frameworks unless and until they are needed. And, frankly, one can go a long way on procedural code with subroutines to gather repetitive code sequences.

(And don’t get me started on functional programming…)

Some time ago, I was tasked to write a LIMS in old perl. Physical ‘aliquots’ with injections of various liquids would be combined and recombined by bio-machines. This led to a dawning realization that these aliquot objects could be modelled in an object style with parent / child relationships. After a few weeks, I proudly delivered my lowly attempt at ‘Mu’ for this (and only this) problem. Kudos to the P6 team – after a couple of weeks in here, it’s just sensational the level of OO power that the real Mu delivers:

Screenshot 2017-09-20 19.32.21

Now, hard at work, on the perl6 version of Physics::Unit, I am wondering how to put the OO theory into productive practice. One of my aims was to find a medium sized (not core tools) problem that (i) I know something about and (ii) would be a good-sized problem to wrangle.

So I am enjoying the chance to design some classes and some interfaces that will make this all hang together. But – as an explorer, it has become clear that I only have three options. The problem runs like this:

  • There is a parent Measure class that contains the methods for any real-world measurement handling dimension, units, value and errors.
  • Then there are child classes for my Distance $d = ’42 m’, my Time $t = 3 s’, etc.
  • First level, I have an operation like … my $r = ’23 ft’ + $d;

Initially I had some success with object types ::T – but these only let you read the type and  duplicate if needed for a new left hand side container. Then I tried the built in (shallow) clone method. But…

  • What about the operation … my $s = $d / $t?
  • How do I create a new Speed object programatically?

Ultimately, thanks to rosettacode.org, I worked out that $x.perl.EVAL with some ~~ s/// substitions on the way would do the trick!

Phew. Please comment below if you have a better way to share – or would like to point out the risks of this technique…

Advertisements

11 thoughts on “Clone Wars”

  1. So I’m on the train at the moment so can’t easily check the docs but I am pretty sure you can make a new multi infix \ operator that matches a Distance on the left and Time on the right and returns a Speed.

    When I get into the office and there are less tunnels I shall try and find some more helpful detail.

    Like

    1. Thanks Simon – that would be much appreciated. I am using an infix to do “Measure Maths” – such as Speed = Distance / Time to handle units and errors. When it comes to the types, these all inherit from a general Measure type. I need to generate a new child at runtime from a string – e.g. my Str $s = ‘Speed’; my ::T = $s; my ::T .=new (value => 42, units => m/s); My understanding of perl6 type variables is that I can load ::T from the infix or method signature if I have that type passed in, but I cannot interpolate a string into it to dynamically set the child Type.

      Like

  2. In Perl 6 types are objects. To create an instance at runtime you need a type literal or a variable that hold the type. To get a type object form a name of a type at runtime, use the ::() dynamic lookup operator.

    my $type = ‘Int’;
    my $type-object = ::($type);
    my $instance = $type-object.new(10);
    dd $instance;
    #OUTPUT: «Int $instance = 10␤»

    Like

  3. So here’s a very quick version of my idea. We define a Unit role and then differnt unit types. Then we can add a new infix / that is a Speed constructor.

    —-

    module SI {

    role Unit {
    has Numeric $.size;
    has Str $.descriptor;

    method Str(–> Str) {
    return “{$.size}{$.descriptor}”;
    }

    method Rat(–> Rat) {
    return $.size.Rat();
    }
    }

    class Distance does SI::Unit {
    submethod BUILD( Numeric :$size ) {
    $!size = $size;
    $!descriptor = ‘m’;
    }
    }

    class Time does SI::Unit {
    submethod BUILD( Numeric :$size ) {
    $!size = $size;
    $!descriptor = ‘s’;
    }
    }

    class Speed does SI::Unit {
    submethod BUILD( Numeric :$size ) {
    $!size = $size;
    $!descriptor = ‘m/s’;
    }
    }

    multi infix:( SI::Distance $d, SI::Time $t –> SI::Speed ) is export {
    return SI::Speed.new( size => $d.size / $t.size );
    }

    }

    Like

    1. I think the amount of user variation expected on inputs – everything from miles per hour through m/sec^2 could use a Grammar. Gives me a chance to try that too! Since only +-*/ make sense I have been planning to overload these in a visible way… need to think about a slang.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s