5

I have

class Length is Measure export { ... }

I want synonyms that differ only in that the class name is different, I have tried this:

class Distance   is Length is export {}
class Breadth    is Length is export {}
class Width      is Length is export {}
class Height     is Length is export {}
class Depth      is Length is export {}

This kind of works in that $distance ~~ Length, but I also want $length ~~ Distance.

Some kind or coercion would be desirable - eg $length.Distance ~~ Distance to discourage operations like $width = $height + $depth (ie you cannot always add lengths that point along different axes).

Maybe some class kind of := name binding, or a shorthand way to coerce NxN?

Any advice most gratefully received...

librasteve
  • 6,832
  • 8
  • 30

2 Answers2

6

This is not yet an answer, but might grow into one.

Is the following heading in useful directions for you? I don't necessarily mean for you to use composition instead of inheritance (role), or direct aliasing (constant), or mixins (but), or a dynamic type constraint (where). The code below is just a quick way to prototype until you provide feedback.

role Measurement {}
role Height does Measurement {}
role Width does Measurement {}
constant Breadth = Width;
say Width;                             # (Width)
say Breadth;                           # (Width)
say ::<Breadth>:kv;                    # (Breadth (Width))
say Breadth ~~ Width;                  # True
say Width ~~ Breadth;                  # True

multi infix:<+>
  (::L Measurement \l, 
       Measurement \r where * !~~ L)
{ fail }

say (42 but Width) + (99 but Breadth); # 141
say (42 but Width) + (99 but Height);  # Failed...
raiph
  • 31,607
  • 3
  • 62
  • 111
  • Hi @raiph - actually I had marked codesections as the Answer - but now I have changed to your as it does not require digging into the ACCEPTS introspection weeds, and I think has a bit more clarity by working at a higher level of abstraction. Also it covers both parts of my "ask". Great answers both! tx... – librasteve Feb 15 '21 at 09:09
4

I'd probably need to see a few more usage cases to be hundred percent sure what the best approach is, but at least with respect to ensuring that all length

class A { 
  method ACCEPTS($other) { $other.isa: A }
}

class B is A { }
class C is A { }
class D is A { }

my $b = B.new;
my $c = C.new;
my $d = D.new;

say $b ~~ D; # True
say $d ~~ C; # True
say $c ~~ B; # True

Because the ACCEPTS is defined on A here, that is what will be used for matching against B/C/D. By default, ACCEPTS smart matches using isa($?CLASS), which is why it returns false, but now it'll lock it into using A always.

Another way is to set the class to an alias. This is normally good for when you want to shorten the name of a longer class you imported from a module, but it will work here too:

class A { ... }
our \B = A;   my $b = B.new;
our \C = A;   my $c = C.new;
our \D = A;   my $d = D.new;

say $b ~~ A & C & D; # True

say $b.WHAT; # A
say $b.WHAT; # A
say $b.WHAT; # A

You'll notice that all these claim to be A because they are. All we've done is give another way to access A. This means that not only does B pass for D or A, it's indistinguishable from them because it's identical to them (down to where it's stored in memory).

user0721090601
  • 5,276
  • 24
  • 41
  • Building on this a bit, it's also possible that you want `A` (or `Length` in your question) to actually be a `Role` rather than a `Class`, depending on the exact relationship you'd like to create. – codesections Feb 13 '21 at 18:58
  • hi @codesections - this is very much what I am after -- I think that the ACCEPTS method will do what I want (and if I choose a lightweight coercion also,I can probably figure how to adjust the ACCEPTS accordingly. In principle I am with you on the composability straights of Roles, however, the stickler in me insists that a Length is a Measure. ;-) – librasteve Feb 15 '21 at 09:02
  • @p6steve ACCEPTS is the function behind smartmatching--you probably knew that already. https://www.nntp.perl.org/group/perl.perl6.users/2019/12/msg7408.html – jubilatious1 Feb 17 '21 at 11:16