Calling .WHY
on something declared returns the special comments built around it. That's pretty cool. How can I refer to a subroutine defined in a class? Is it always hidden? I'm curious about modules that provide subroutines instead of classes (for which the answer might be "don't do it that way"). I'm mostly playing around with the limits of .WHY
and how far I can take it.
#| This is the outside bit
sub outside { 137 }
put &outside.WHY; # This works
#| Class Foo is an example
class Foo {
#| The bar method returns a number
method bar { 137 }
#| quux is a submethod
submethod quux { 137 }
#| qux is private
submethod !qux { 137 }
#| The baz method also returns a number
sub baz { 37 }
put &baz.WHY; # this works in this scope
}
put "---- With an object";
quietly {
my $object = Foo.new;
put "As object: ", $object.WHY;
# sub is not really a method?
put "As object - bar: ", $object.^find_method( 'bar' ).WHY;
# should this work? It *is* private after all
put "As object - qux: ", $object.^find_method( 'qux' ).WHY;
}
put "---- With class name";
quietly {
put Foo.WHY;
put "As class lookup: ", ::("Foo").WHY;
put "As class lookup (quux): " ~ Foo.^lookup( 'quux' ).WHY;
put "As class lookup (baz): " ~ Foo.^lookup( 'baz' ).WHY; # nope!
# this is the part where I need help
put "As :: lookup: ", ::("Foo")::("&baz").WHY; #nope
}
Here's the output:
This is the outside bit
The baz method also returns a number
---- With an object
As object: Class Foo is an example
As object - bar: The bar method returns a number
As object - qux:
---- With class name
Class Foo is an example
As class lookup: Class Foo is an example
As class lookup (quux): quux is a submethod
As class lookup (baz):
As :: lookup:
It's that last line of output I'm asking about. How can I get to a subroutine defined in a class?
# should this work? It *is* private after all put "As object - qux: ", $object.^find_method( 'qux' ).WHY;
Both of the following work:
put "As object - qux: ", $object.^find_private_method('qux').WHY;
put "As object - qux: ", $object.^private_method_table<qux>.WHY;
(find_private_method
doesn't seem to be documented in p6doc, so I'm not sure if it is official API. private_method_table
is documented, although not really explained.)
# this is the part where I need help put "As :: lookup: ", ::("Foo")::("&baz").WHY; #nope
This one works if you declare sub baz { 37 }
as our sub baz { 37 }
.
You can also write the lookup more simply as:
put "As :: lookup: ", &Foo::baz.WHY;
The our
declarator (explained in Synopsis 3, section "Declarators") associates a symbol with the current package – in this case, a class – so that it can be accessed from outside of it using the ::
syntax.
By default, subroutines are lexically scoped – i.e. their default declarator, if none is specified, is my
. (The statement sub baz { 37 }
has basically1 the same effect as writing my &baz := sub { 37 }
at the top of the curly-brace-delimited scope.)
By writing our sub baz { 37 }
, you're telling it to use our
instead of my
scoping.
I'm curious about modules that provide subroutines instead of classes
Either declare it with our
as shown above (in which case the user scope will have to use the fully qualified name Foo::baz
), or export it into the user scope (in which case they can refer to it as just baz
).
The easiest way to make a symbol exportable, is to use the is export
trait:
module Foo { #| The baz method also returns a number sub baz is export(:ALL) { 37 } } import Foo :ALL; say &baz.WHY;
A use
statement implicitly calls import
on the module in question. Since here the module is defined in the same file, we can just call import directly.
Note that you can also write sub baz is export { 37 }
(without the :ALL
), in which case the symbol would be imported by default whenever the class is use
'd or import
'ed. But in the Perl 5 / CPAN community that's considered bad practice, and letting users import individual symbols is recommended. In Perl 6, importing individual symbols doesn't work yet, so I recommend using the :ALL
tag for now.
1) The only difference I'm aware of, is that in the first case the routine knows its own name for introspection purposes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With