Skip to content

Instantly share code, notes, and snippets.

@Xliff
Last active July 28, 2019 19:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xliff/2123bdc09b0fd5afa192201d748e0700 to your computer and use it in GitHub Desktop.
Save Xliff/2123bdc09b0fd5afa192201d748e0700 to your computer and use it in GitHub Desktop.
multi and the ability to override...

I'm getting this error in some code:

Ambiguous call to 'new(Clutter::Stage: Clutter::Raw::Types::ClutterActor)'; these signatures all match:
:(Clutter::Actor: Clutter::Raw::Types::ClutterActor $actor, *%_)
:(Clutter::Stage: Mu $stage where { ... }, *%_)

Here is the offending signature from Clutter::Stage, which is a descendant of Clutter::Actor:

our subset StageAncestry is export of Mu
  where ClutterStage | ActorAncestry;
  ...
class Clutter::Stage is Clutter::Actor {
  ...
  multi method new (StageAncestry $stage) {
    self.bless(:$stage);
  }
}

And here is the conflicting part from Clutter::Actor:

our subset ActorAncestry is export of Mu
  where ClutterAnimatable | ClutterContainer | ClutterScriptable | ClutterActor;
...
class Clutter::Actor {
  ...
  multi method new (ClutterActor $actor) {
    self.bless(:$actor);
  }

Why isn't Clutter::Stage's new always selected over the method in Clutter::Actor?

@Xliff
Copy link
Author

Xliff commented Jul 28, 2019

Ah! The solution is to use is default to handle the ambiguity. The best part... it does follow the MRO. Consider:

 class A { multi method a {}; }; class B is A { multi method a is default {}; }; class C is B { multi method a is default { 'C'.say }; };  C.new.a

# Output: C

...and...

class A { multi method a {}; }; class B is A { multi method a is default { 'B'.say }; }; class C is B { multi method a is default { 'C'.say }; };  B.new.a

# Output: B

Thanks to timotimo in #perl6!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment