I use Package::Generator for this sort of thing, now, but it's pretty gross.
my $package = Symbol::table;
Symbol::set_variables(
$package => [
version => \1.00,
ISA => [ qw(Base OtherBase) ],
do_stuff => sub { ... }
],
);
I have *no* idea what is required to make this happen. I can see problems,
especially with things that already deal with symbol tables by expecting that
every package is just a string. There will need to be either magic or forward
incompatibility.
--
rjbs
We did have a form of anonymous package, which has been deprecated,
and that can be now replaced by something that works:
[rafael@stcosmo ~]$ perl5.8.8 -wepackage
Use of "package" with no arguments is deprecated at -e line 1.
[rafael@stcosmo ~]$ bleadperl -wepackage
syntax error at -e line 1, at EOF
Execution of -e aborted due to compilation errors.
However some more thought on the syntax is needed, of course.
Yeah, at first I thought I'd suggest, in my sample:
my $package = package;
...and then I saw that 0-arg package existed. Its current behavior is bizarre,
though. Ditching it seems like a good idea, but then making "package" alone
return an anonymous package is just weird (to me).
I think we're better off with something new to return the anonymous package.
--
rjbs
In my Class::Mix module (on CPAN), I had a need to create packages
dynamically for anonymous classes. I encapsulated that as the function
genpkg() in that module. It can't generate a package with literally
no name, of course, because packages are referred to strictly by their
character-string name. Instead it generates a name that is unlikely to
clash with anything deliberately constructed (and it checks that there
isn't actually a clash before returning the name). This is much like the
"gensym" concept seen in Lisp.
I think you'll have difficulty getting away from string names for
packages altogether. There's a lot of code that expects to do symbolic
referencing using package names and string operations. Better to
incorporate something like genpkg(). Suppose you were to allow an
arbitrary expression as the argument to "package", rather than just a
bareword, you could do things like:
use Class::Mix qw(genpkg);
package genpkg();
sub foo { 123 }
$main::anon_package = __PACKAGE__;
though actually to me that doesn't seem like a huge win over the present:
use Class::Mix qw(genpkg);
my $pkg = genpkg();
no strict "refs";
*{"$pkg\::foo"} = sub { 123 };
$main::anon_package = $pkg;
-zefram
Sorry if this is a very bad idea, but what about:
my $anon = package {
sub new {
my ($p) = @_;
return bless {}, $p;
}
};
But what would $p be? Could there be a named package passed in like $p? For
example, could I do:
my $p = package Foo::Bar;
if (ref $p eq 'PACKAGE') {
print "Moo.\n";
}
Just my €0.02 :)
-rs
Right. This is what Package::Generator does, as well.
> I think you'll have difficulty getting away from string names for
> packages altogether. There's a lot of code that expects to do symbolic
> referencing using package names and string operations. Better to
> incorporate something like genpkg(). Suppose you were to allow an
> arbitrary expression as the argument to "package", rather than just a
> bareword, you could do things like:
Anonymous packages would, I'd hope, be scoped items that could be garbage
collected normally. (I that if in-scope X is blessed into package Y, there is
a reference to Y.)
Right now, I work around this, when necessary, with Package::Reaper.
--
rjbs
> I think you'll have difficulty getting away from string names for
> packages altogether. There's a lot of code that expects to do symbolic
> referencing using package names and string operations. Better to
> incorporate something like genpkg(). Suppose you were to allow an
> arbitrary expression as the argument to "package", rather than just a
> bareword, you could do things like:
>
> use Class::Mix qw(genpkg);
> package genpkg();
> sub foo { 123 }
> $main::anon_package = __PACKAGE__;
use Macrame;
EXPAND "package HARD2GUESS".substr(rand(1),2);
no Macrame;
;
Alternately ...
my $anon_pkg = Class::MOP::Class->create_anon_class(
superclasses => [ 'Some::Base::Class' ],
methods => {
'foo' => sub { 123 },
'baz' => sub { 456 }
}
);
$main::anon_package = $anon_package->name;
This also has the added benefit/drawback that once $anon_package goes
out of scope the package will get deleted. It should be noted that if
you use the Class::MOP constructor, any instances of this anon-class
will hold a ref to the class and therefore keep it around as well.
- Stevan
See also:
my $reaper = Package::Reaper->new( Package::Generator->new_package( ... ) );
I wonder how many other solutions are out there.
--
rjbs