I'm rewriting a framework from Perl5 to Perl6 for my work purposes. At some place I need to collect information from other modules/classes by executing a public sub
they might provide; or they may not. So, it necessary to find out if the sub
is present. This is not a big deal when a module is referenced directly (Foo::<&my-sub>
) or by a symbolic name in a string (&::("Foo")::my-sub). But for the simplicity of it I would like to allow to pass module names as-is (lets say collector
is the method collecting the info):
self.collector( Foo );
Where Foo
could be the following:
module Foo {
use Bar;
use Baz;
our sub my-sub { Bar, 'Baz' }
}
And this is where I'm missing something important from Perl6 syntax because the following:
method collector ( $mod ) {
my $mod-name = $mod.WHO;
my @mods;
with &::($mod-name)::my-sub {
@mods.push: &$_();
}
}
is currently the only way I can perform the task.
I didn't try a type capture yet though. Should work as expected, I guess. So, the question is more about extending my knowelge of the syntax.
Code Introspection is used for examining the classes, methods, objects, modules, keywords and get information about them so that we can utilize it. Introspection reveals useful information about your program’s objects.
This module has two variables and a class called student. The variable section can be used in another module as it is prefixed with the keyword “export” but the student_name variable cannot be accessed in another module as it is not prefixed with the keyword “export”.
Everything in python is an object. Every object in Python may have attributes and methods. By using introspection, we can dynamically examine python objects. Code Introspection is used for examining the classes, methods, objects, modules, keywords and get information about them so that we can utilize it.
How to allow classes defined in a module to be accessible outside of a module ? In typescript by using an import statement, a module can be utilized in another module. any variables, classes, methods, or other objects declared in a module are not accessible outside of it.
The final solution from the exchange with Vadim in the comments on their question. It's arguably insane. They think it's beautiful. And who am I to argue? .oO( Haha, hoho, heehee... )
my $pkg-arg = (Int, 'Int').pick;
my \pkg-sym = $pkg-arg && ::($pkg-arg);
my \sub-ref = &pkg-sym::($subname);
There are two obviously useful ways to refer to a package:
Its symbolic name. Int
is the symbolic name of the Int class.
Its string name. 'Int'
is the string name of the Int class.
Vadim, reasonably enough, wants a solution for both.
In the solution in this answer I simulate the two types of argument by randomly picking one and assigning it to $pkg-arg
:
my $pkg-arg = (Int, 'Int').pick;
Now we need to normalize. If we've got a symbolic name we're good to go. But if it's a string name, we need to turn that into the symbolic name.
Vadim showed a couple ways to do this in the comments on their question. This solution uses a third option:
my \pkg-sym = $pkg-arg && ::($pkg-arg);
If $pkg-arg
is a symbolic name, it'll be False
. With a False
LHS the &&
short-circuits and returns its LHS. If $pkg-arg
is a string name, then the &&
will instead return its RHS, which is ::($pkg-arg)
which is a symbol lookup using $pkg-arg
as a string name.
The upshot is that pkg-sym
ends up containing a package symbolic name (or a Failure
if the lookup failed to find a matching symbolic name).
Which leaves the last line. That looks for a sub named $subname
in the package pkg-sym
:
my \sub-ref = &pkg-sym::($subname);
The &
is needed to ensure the RHS is treated as a reference rather than as an attempt to call a routine. And pkg-sym
has to be a sigilless identifier otherwise the code won't work.
At the end of these three lines of code sub-ref
contains either a Failure
or a reference to the wanted sub.
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