Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does perl6 multi default to sub?

Tags:

dispatch

raku

In reference to this question / answer, perl6 multi defaults to sub.

No such method <name> for invocant of type <class>

I would have expected it to default to method. Please could someone explain the rationale for this?

like image 349
p6steve Avatar asked Jul 14 '18 20:07

p6steve


2 Answers

A multi declarator (multi, proto, or only) that is not followed by some other kind of declarator, but instead a routine name, will always be short for the sub declarator.

Perl 6 is keen on lexical scoping, and especially keen on making code easy to refactor.

Making the shortest way to declare a multi take the most narrowly scoped option - lexical scope - encourages keeping things as narrowly scoped as possible.

Making multi without a declarator have a consistent meaning aids refactoring, by allowing one to confidently move the code to the narrowest scope in which it is required. Having it suddenly change meaning just because it was moved into a class would be a refactoring frustration.

Finally, it's worth noting that sub in Perl 6 can be seen as filling the same niche as private static in various other languages, that multiple dispatch is generally useful, and thus a multiple dispatch sub can therefore be useful inside of a class body.

Sometimes special cases are justified. Like natural languages, Perl 6 will make them when it's really worth it, but the default is to avoid them. The argument for multi meaning something else inside of a class (and presumably role) just isn't strong enough for a special case.

like image 131
Jonathan Worthington Avatar answered Nov 20 '22 12:11

Jonathan Worthington


A sub can occur anywhere and defaults to lexical scoping rules (my).
A method usually occurs only in a class definition and it defaults to being scoped to a class (has).

my multi sub foo (){…}
multi foo (){…} # identical

my multi method foo (){…} # must be forced to my declaration


class :: {
  my multi sub foo (){…}
  multi foo (){…} # identical

  has multi method bar (){…}
  multi method bar (){…} # identical
}


sub :: () {
  my multi sub foo (){…}
  multi foo (){…} # identical

  my multi method foo (){…} # must be forced to my declaration
}

method :: () {
  my multi sub foo (){…}
  multi foo (){…} # identical

  my multi method foo (){…} # must be forced to my declaration
}

Since a sub can, and does occur everywhere, it makes more sense for multi to imply a sub rather than method.

While you may think that it would make sense for multi to imply a method in a class definition; that would make it so that multi implies two different things (times two) depending on context. It would imply my sub outside of a class, and has method inside of a class. (It would also go back to my sub inside of a method inside of a class.)

That is it would be a special case. One of the design goals of Perl 6 is to reduce the number of special cases.

like image 7
Brad Gilbert Avatar answered Nov 20 '22 11:11

Brad Gilbert