'Reuse parent symbols in child module

I am seeking to re-use the same role/class names in a child module as in its parent. You know, like a specialization.

The aim is to be able to re-use the same script code for both the parent and child Series variants by simply changing use Dan to use Dan::Pandas at the top.

I am trying to stick to role rather than class compostion where I can so that the behaviours can be applied to other objects with eg. class GasBill does Series;

Here is the MRE:

me@ubuntu:~/spike# tree
.
├── lib
│   ├── Dan
│   │   └── Pandas.rakumod
│   └── Dan.rakumod
└── spike.raku

Dan.rakumod:

  1 unit module Dan;
  2 
  3 role Series is export {
  4     method no { "no" }
  5 }

Pandas.rakumod:

  1 unit module Dan::Pandas;
  2 
  3 use Dan;
  4 
  5 role Series does Dan::Series is export {
  6     method yo { "yo" }
  7 }

spike.raku:

  1 use lib './lib';
  2 use Dan::Pandas;
  3 
  4 my $s = Series.new;                  #version 1                      
  5 #my $s = Dan::Pandas::Series.new;    #version 2 "fqm"
  6 
  7 say $s.no, $s.yo, $s.^name;

My version 1 says:

No appropriate parametric role variant available for 'Dan::Series':
    Ambiguous call to '(Dan::Series)'; these signatures all match:
      (::$?CLASS ::::?CLASS Mu $)
      (::$?CLASS ::::?CLASS Mu $)
  in block <unit> at spike.raku line 4

My version 2 says:

Could not find symbol '&Series' in 'Dan::Pandas'
  in block <unit> at spike.raku line 5

I am trusting that raku does have a way to do this, but darned if I can work it out!



Solution 1:[1]

If I'm understanding correctly, you don't need/want to use the non-specialized role in the final module (that is, you aren't using the Series defined in Dan.rakumod in spike.raku – you're only using the specialized Series defined in Pandas.rakumod). Is that correct?

If so, the solution is simple: just don't export the Series from Dan.rakumod – it's still our scoped (the default for roles) so you can still use it in Pandas.rakumod exactly the way you currently do (Dan::Series). But, since it's not exported, you it won't create a name clash with the non-prefixed Series.

Solution 2:[2]

My Solution

Taking the advice of @codesections [that FQMs can be used without is export] and @raiph [that you can qualify the export with e.g. is export(:ALL)], then - yes - there is a neat way to do this.

viz. https://docs.raku.org/language/modules#Exporting_and_selective_importing

Turns out that this is low touch (just change two lines) and, as I originally hoped, something that raku designers have anticipated.

Here is the code from my OP adjusted...

Dan.rakumod:

  1 unit module Dan;
  2 
  3 role Series is export(:ALL) {    #<== added the selective export
  4     method no { "no" }
  5 }  

Pandas.rakumod (no change):

  1 unit module Dan::Pandas;
  2 
  3 use Dan;
  4 
  5 role Series does Dan::Series is export {
  6     method yo { "yo" }
  7 }  

spike.raku:

  1 use lib './lib';
  2 #use Dan::Pandas;     #\ either of these work
  3 use Dan :ALL;         #/ <== use :ALL to get 'Series'
  4 
  5 my $s = Series.new;
  6 
  7 say $s.no, $s.yo, $s.^name;  #No such method 'yo' if Pandas not used

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 codesections
Solution 2 p6steve