Skip to content

Instantly share code, notes, and snippets.

@skids
Last active August 29, 2015 14:26
Show Gist options
  • Save skids/9fe5f64d7ce65c2c1695 to your computer and use it in GitHub Desktop.
Save skids/9fe5f64d7ce65c2c1695 to your computer and use it in GitHub Desktop.
Implicit named slurpy
On the subject of whether methods should have implicit *%_ or not I figured
some side-by-side examples would be useful to help the community come to
a decision.
Note that Mu.new will still have a prototype of *%_. So banning
unknown named parameters will require custom constructors in either case,
so we'll use them in the examples.
EXAMPLE: Only allow one optional/default argument to a method
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::A { | class N::A {
method foo (|c (:$a = 1)) { | method foo (:$a = 1) {
... | ...
} | }
} | }
EXAMPLE: Allow arbitrary nameds while supplying a default to a particular named
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::B { | class N::B {
method foo (:$b = 1) { | method foo (:$b = 1, *%_) {
... | ...
} | }
} | }
EXAMPLE: subclass the *::A class and add a new optional/default named parameter,
keeping restriction against unknown parameters, when the old parameter is unused in the subclass
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::C does M::A { | class N::C does N::A {
method foo (|c (:$a?, :$c = 1)) { | method foo (:$a?, :$c = 1) {
... | ...
nextwith(:$a); | nextwith(:$a);
} | }
} | }
EXAMPLE: subclass the *::B class and add a new optional/default named parameter,
still with no restricition against unknown parameters, when the old parameter is unused in the subclass
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::D does M::B { | class N::D does N::B {
method foo (:$c = 1) { | method foo (:$c = 1, *%_) {
... | ...
nextsame; | nextsame;
} | }
} | }
EXAMPLE: subclass the *::A class and add a new optional/default named parameter,
keeping restriction against unknown parameters, when the old parameter is used
and mandatory in the subclass
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::E does M::A { | class N::E does N::A {
method foo (|c (:$a!, :$c = 1)) { | method foo (:$a!, :$c = 1) {
... # Do something with $a | ... # Do something with $a
nextwith(:$a); | nextwith(:$a);
} | }
} | }
EXAMPLE: subclass the *::B class and add a new optional/default named parameter,
still with no restricition against unknown parameters, when the old parameter is
mandatory and used in the subclass
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::F does M::B { | class N::F does N::B {
method foo (:$b!, :$c = 1) { | method foo (:$b!, :$c = 1, *%_) {
... # Do something with $a | ... # Do something with $a
nextsame; | nextsame;
} | }
} | }
So the basic examples really boil down just to the difference between whether paradigm
N has to write (|c (#'signature)) everywhere or on the other side whether paradigm M has
to write (#'signature , *%_) everywhere.
Lets look at what happens when a someone wants to make an N subclass of an M class and vice
versa.
EXAMPLE: Subclass the *::A class so that it accepts (and ignores) unknown named parameters.
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::G does M::A { | class N::G does N::A {
method foo (:$a) { | method foo (:$a, *%_) {
... | ...
nextwith(:$a) | nextwith(:$a)
} | }
} | }
EXAMPLE: Subclass the ::*B class to not accept unknown named parameters
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::H does M::B { | class N::H does N::B {
method foo (|c (:$b? )) { | method foo (:$b?) {
... | ...
nextsame; | nextsame;
} | }
} | }
EXAMPLE: Patch the *::C class because the maintainer of the *::A class added a new named
optional parameter and you want to allow the subclass to use it.
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::C does M::A { | class N::C does N::A {
- method foo (|c (:$a?, :$c = 1)) { | - method foo (:$a?, :$c = 1) {
+ method foo (|c (:$a?, :$c = 1, :$d?)) { | + method foo (:$a?, :$c = 1, :$d?) {
... | ...
- nextwith(:$a); | - nextwith(:$a);
+ nextwith(:$a, :$d); | + nextwith(:$a, :$d);
} | }
} | }
EXAMPLE: Patch the *::D class because the maintainer of the *::B class added a new named
optional parameter and you want to allow the subclass to use it.
AS IS | NO IMPLICIT *%_
--------------------------------------------------|-------------------------------------------------------
class M::D does M::B { | class N::D does N::B {
method foo (:$c = 1) { | method foo (:$c = 1, *%_) {
... | ...
nextsame; | nextsame;
} | }
} | }
(no patch needed)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment