How can I create an object of an anonymous class with inheritance using bless?
I guess I need to set #ISA, but how do I accomplish that using strict?
After a hint of райтфолд I took a look at Class::Inner. They solve the inheritance by
no strict 'refs';
#{"$anon_class\::ISA"} = $parent;
Is there a way to accomplish that still using strict refs?
Use parent to set the base classes for your class. bless has nothing to do with inheritance:
package Derived;
use warnings;
use strict;
use parent qw(Base);
sub new {
my $class = shift;
return bless {}, $class;
}
If you are playing with those things you can sometimes violate strict. Pragma strict is there to protect you from mistakes. If you are sure what you are doing it is absolutely OK to switch off strict in some limited scope and preferably limited to the specific thing as you have in your OP. So this code is fine when you know what you do
{
no strict 'refs';
#{"$anon_class\::ISA"} = ($parent);
}
Is there a way to accomplish that still using strict refs?
Why? This is exactly the thing strict is designed to catch. Sure, you can fool strict, but it's far better to be clear about the fact that you are doing something strict normally forbids.
In my opinion,
{ no strict 'refs'; #{ $anon_class . '::ISA' } = $parent; }
is far better than using eval or %:: (even if it they weren't longer).
Related
Normally when I build a data structure in Perl, I end up having to declare it from %leaf to %root, so I have been tinkering with a module that would allow me to build up from
$seed to $seed->trunk->branch->leaf.
It's not difficult with AUTOLOAD and new subroutines. My question for SO is how do I detect if the 'strict' pragma is in use, so that the module runs in a different mode that would require the variables to be "declared" before usage so I don't accidently assign a value to $seed->drunk when I'm using strict -- assume that the module is called branch and this is valid syntax for module usage
$seed->declare('trunk');
$seed->trunk(new branch);
$seed->trunk->declare('leaf');
$seed->trunk->leaf("value");
How do I detect if the strict pragma is in effect in the calling program from the module?
It may be that this is not possible -- in which case I'd have to use a static variable to handle module independent pragmas.
EDITED / POSTSCRIPT:
I coded out the initial version that doesn't check for 'strictness' or implement a 'declare' subroutine and realized that the autoloader would not provide a simple enough user syntax if it operated by reference, so I wrote it to check for the first parameter and assign the value passed to an element in the object's referred hash table, otherwise if there was no parameter it would return the value of the element specified.
So I am posting the code for the branch module to satisfy your curiosity. Mind you, I haven't implemented a check for strictness, yet.
package branch;
sub new
{
my $type = shift;
my $self = { };
bless $self, $type;
return $self;
}
sub DESTROY
{
my $self = shift;
%$self = undef;
}
sub AUTOLOAD
{
my $self = shift;
my $value = shift;
my $sub = $AUTOLOAD;
my ($type, $PROGRAM) = ($sub =~ /(.*)::(.*)/);
if( $value ne undef )
{
$$self{$PROGRAM} = $value;
return $value;
}
return $$self{$PROGRAM};
}
1;
Well the first thing would be, strict what? Strict has three subpragmas, with their own behaviors and bits to check. use strict 'refs' doesn't allow you to dereference strings; use strict 'vars' doesn't allow you to access global variables in an unqualified way, and use strict 'subs' disables barewords outside of a few situations. use strict equates to all three, but none of them really seems close enough to what you're asking for to be worth piggy-backing on.
So to answer your question somewhat directly: element [8] in the list returned by caller($i) returns the compile hint bits in effect for the $ith level caller. If you peek in strict.pm you can see the bits that each subpragma sets and check for them at the caller level that corresponds to the code that's actually calling your method.
But, returning to my original point, you probably shouldn't, because that's not what strict is about. You should either accept an option on your objects' constructor that decides whether they should behave strictly or not, or if you really want a lexical pragma instead of something that follows your objects around, you should write your own using the information in perlpragma as a tutorial. All perls since 5.10 support arbitrary user-defined pragmas using the %^H hints hash which is exposed as element [10] of the caller info.
You seem to be confused about the scoping of the strict pragma.
If a module uses strict, this doesn't enforce anything on the user of the module. Even if you want to extend the package, by subclassing or monkey-patching in additional methods.
use strict only applies to the file it is used within. (Or if it's used within a pair of curly braces, it only applies up until the closing brace.) So if you're extending a package, just do it within a separate file, and none of the pragmas applied in the original module will apply to your code.
That said, it's rarely a good idea to not use strict. There are occasional tasks where it might be useful to disable it in a small scope, but the problem you are describing doesn't seem to be one of them.
In particular, if you're building a deeply nested structure, only don't need to declare every level. Demonstration:
use strict;
use warnings;
use Data::Dumper;
my $root;
$root->{trunk}{branch}{leaf} = 42;
print Dumper($root);
Moose is very lovely, but sometimes simple typos can cause hair-raisingly exciting long stacktraces with, from my point of view, zero useful content.
So, are there any tools to interpret this exploding into something helpful?
In particular for classes using plain Moose, Moose+MooseX::Method::Signatures, and MooseX::Declare.
The tools only need to be helpful while developing to catch those typo or thinko problems that make things just not work.
=========================
Following suggestion below, I'm using this not-quite-a-module-yet which is reducing my headaches a little, more ideas welcome, though:
package MooseX::QuietCarping;
# Not actually a Moose thing, but helpful for Moose.
# calm Moose-internal stacktraces down a little
use Carp;
my %retain = ();
sub import {
my $class = shift;
$retain{$_}++ for #_;
}
CHECK {
for (sort keys %INC) {
s{\.pm$}{};
s{[/\\]}{::}g; # CROSS PLATFORM MY ARSE
next if $retain{$_};
$Carp::Internal{$_}++ if /^(?:Class::MOP|Moose|MooseX)\b/
}
%retain = (); # don't need this no more
}
1;
One way I experimented with some time ago is putting Moose related classes into %Carp::Internal hash, something like this:
$Carp::Internal{$_}++ for qw{
Class::MOP
Class::MOP::Attribute
Class::MOP::Class
...
};
Such classes will be skipped in stack trace, making it more compact and emphasizing your own code.
You can find them by traversing %INC variable:
package Dummy;
use Moose;
use MooseX::Declare;
# use ....;
for (sort keys %INC) {
s{\.pm$}{};
s{/}{::}g;
print "$_\n" if /^(Class::MOP|Moose|MooseX)\b/;
}
I seem to recall seeing a PerlMonks post by stvn a week or two ago saying that they're working on improving the Moose error messages. I don't think there's anything currently available to clean the up, though.
Method::Signatures::Modifiers is a package which hopes to fix some of the problems of MooseX::Method::Signatures. Simply use it to overload.
use MooseX::Declare;
use Method::Signatures::Modifiers;
class Foo
{
method bar (Int $thing) {
# this method is declared with Method::Signatures instead of MooseX::Method::Signatures
}
}
Looking into the Const::Fast source I noticed that it used the built-in function Internals::SvREADONLY internally. Is it safe to use that function directly in my Perl script? It seems to be present in core from Perl 5.8.
my $PI = 4 * atan2 1, 1;
Internals::SvREADONLY($PI => 1);
$PI = 2.718; # Modification of a read-only value attempted at ..
C:\>perldoc Internals
No documentation found for "Internals".
No.
More specifically, the package is named "Internals" for a reason. It is not intended for use outside the core. It could change without notice.
This is not quite answering your question, but I think it is worth mentioning so others don't experience the same pain as I have: don't use any readonly value if you're running on a version of Perl earlier than 5.10.1. Consider this little example:
{
package Foo;
sub foo { print "I'm in foo!\n"; }
}
use strict;
use warnings;
use Readonly;
Readonly my #classes => qw(Foo);
foreach my $class (#classes)
{
# this dies with "Can't call method "foo" without a package or object reference"
$class->foo;
}
Since my XS-fu is not very high, I can't explain what is going on here very coherently (but Devel::Peek shows some interesting things in the $class variable).
How do I list available methods on a given object or package in Perl?
There are (rather too) many ways to do this in Perl because there are so many ways to do things in Perl. As someone commented, autoloaded methods will always be a bit tricky. However, rather than rolling your own approach I would suggest that you take a look at Class::Inspector on CPAN. That will let you do something like:
my $methods = Class::Inspector->methods( 'Foo::Class', 'full', 'public' );
If you have a package called Foo, this should do it:
no strict 'refs';
for(keys %Foo::) { # All the symbols in Foo's symbol table
print "$_\n" if exists &{"Foo::$_"}; # check if symbol is method
}
use strict 'refs';
Alternatively, to get a list of all methods in package Foo:
no strict 'refs';
my #methods = grep { defined &{"Foo::$_"} } keys %Foo::;
use strict 'refs';
if you have a package that is using Moose its reasonably simple:
print PackageNameHere->meta->dump;
And for more complete data:
use Data::Dumper;
print Dumper( PackageNameHere->meta );
Will get you started. For everything else, theres the methods that appear on ->meta that are documented in Class::MOP::Class
You can do a bit of AdHoc faking of moose goodness for packages without it with:
use Class::MOP::Class;
my $meta = Class::MOP::Class->initialize( PackageNameHere );
and then proceed to use the Class::MOP methods like you would with Moose.
For starters:
$meta->get_method_map();
use Moose; #, its awesome.
In general, you can't do this with a dynamic language like Perl. The package might define some methods that you can find, but it can also make up methods on the fly that don't have definitions until you use them. Additionally, even calling a method (that works) might not define it. That's the sort of things that make dynamic languages nice. :)
What task are you trying to solve?
A good answer from How to get structure and inheritance history
The classes from which an object's class currently inherits can be found using the following:
use mro qw( );
use Scalar::Util qw( blessed );
say join ", ", #{ mro::get_linear_isa(blessed($o)) };
If inside my code I'll have calls like:
__PACKAGE__->method;
will this limit the usability of this module, if this module is inherited?
It depends on what you want to do:
#!/usr/bin/perl
package A;
use strict; use warnings;
sub new { bless {} => $_[0] }
sub method1 {
printf "Hello from: %s\n", __PACKAGE__;
}
sub method2 {
my $self = shift;
printf "Hello from: %s\n", ref($self);
}
package B;
use strict; use warnings;
use parent 'A';
package main;
my $b = B->new;
$b->method1;
$b->method2;
Output:
Hello from: A
Hello from: B
If you intend to inherit that method, call it on the referent and don't rely on the package you find it in. If you intend to call a method internal to the package that no other package should be able to see, then it might be okay. There's a fuller explanation in Intermediate Perl, and probably in perlboot (which is an extract of the book).
In general, I try not to ever use __PACKAGE__ unless I'm writing a modulino.
Why are you trying to use __PACKAGE__?
That depends. Sometimes __PACKAGE__->method() is exactly what you need.
Otherwise it's better to use ref($self)->class_method() or $self->method().
"It depends." is the correct answer. It is relatively uncommon to actually need the package name; usually you will have an instance or a class name to start with. That said, there are times when you really do need the package name -- __PACKAGE__ is clearly the tool for that job, being superior to a literal. Here are some guidelines:
Never call methods off __PACKAGE__ inside methods, as doing so makes it impossible for inheritors to change your implementation by simply overriding the called method. Use $self or $class instead.
Try to avoid __PACKAGE__ inside methods in general. Every use of __PACKAGE__ adds a little bit of inflexibility. Sometimes, inflexibility is what you want (because you need compile-time resolution or badly want to control where information is being stored), but be triply sure that what you want is worth the cost. You'll thank yourself later.
Outside of methods, you don't have access to a $self, and should call methods off __PACKAGE__ rather than a literal. This is mostly important for compile-time declarations like those provided by Class::Accessor.