Yesterday (at least I think it was yesterday, excuse the laziness) I released a pragma called namespace::clean. The short explanation for what this module does is this: When use'd, it will build a list of current functions in the package, and install a handler to call after the requesting modules compile time (via Filter::EOF) in which it removes those entries from the symbol table.
The long explanation is that you can import functions into your namespace, or even declare your own functions, that won't show up as methods on calls on your classes and instances. Previously, it always felt ugly to me to import functions (read: Carp, aliased, Scalar::Util & Co,Scalar::Util::weaken(). The same ugliness overwhelms me everytime I put (proper documented) functions in OO packages, so a lot of them end up as methods, even if they don't need to. That's where this module joins the game.
Here is a simple demonstration: Let's define a usual object oriented class:
package Foo;
use warnings;
use strict;
use Carp qw( croak );
sub double {
my $number = shift;
return $number * 2;
}
sub new {
my ($class, $number) = @_;
bless {number => double($number)}, $class;
}
1;
This package will contain three functions: croak, double and new. But we actually just want new available as a method. Not because of coworkers, since they should refer to the hopefully complete and well written documentation, but to prevent conflicts with sub- and future base-classes.
Anyway, after compile-time the calls to the functions are already bound in the code and the actual symbol table entries aren't needed anymore. So we put a line reading use namespace::clean; in our code at the position where all the functions to remove are defined:
package Foo;
use warnings;
use strict;
use Carp qw( croak );
sub double {
my $number = shift;
return $number * 2;
}
use namespace::clean;
sub new {
my ($class, $number) = @_;
bless {number => double($number)}, $class;
}
1;
After this, the following will work correctly:
my $foo = Foo->new(23);
print $foo->{number}; # prints 46
But these will both return undef:
my $can_double = $foo->can('double');
my $can_croak = $foo->can('croak');
So, that's it. I'd very much appreciate some comments. I'm currently thinking about no namespace::clean; and unimport magick for being able to build excludable parts.
Update: 0.02 has just entered the PAUSE and will be available soon.
Huh? (Score:1)
I don't buy it:
Re: (Score:1)
Hrm, point for you. Bad wording on my side. What's the thing called methods are looked up from then? :)
I honestly thought a
delete $Foo::{bar}will remove the symbol table entry.Thanks again!
Ordinary morality is for ordinary people. -- Aleister Crowley
Re: (Score:1)
You misunderstood what chromatic said. He demonstrated that Perl does not have compile-time binding, contrary to what you are saying. Decompiling shows that the invocation of
doublein thenewmethod is indirected via the package. If you remove the entry fordoublefrom the package, the function call will NOT work.Sorry, but your approach won’t work.
Here’s a pattern for you to read carefully and chew on:
Re: (Score:1)
So, you're saying what? I can understand that as either
And btw: You call that a pattern? I call that a work-around :) And, just FYI, you might want to stay away from patronising phrases like "Here’s a pattern for you to read carefully and chew on." Because it really decreases my motivation to answer.
Ordinary morality is for ordinary people. -- Aleister Crowley
Re: (Score:1)
You said:
It’s bad wording on your part to say the functions are bound in the code, because they’re not; they’re always looked up from the symbol table.
Interestingly, what you’re doing shouldn’t work – but it does! Apparently the
%main::-type hashes aren’t actually an interface to the symbol table, they’re just a one-way mirror:Re: (Score:1)
Of course. Did you honestly think I sent some code off to CPAN without even _trying_ first? :)
Maybe I will post it there if nobody else does.
That might be what you (and MJD) think, but I clearly see a difference betw
Ordinary morality is for ordinary people. -- Aleister Crowley
Re: (Score:1)
No, it’s not. A pattern is a common, complex arrangement of language primitives that has to be aligned just so in order to work; which arrangement addresses a particular problem commonly encountered when using the language.
Far from everything in a program does meets this definition. Most notably, the solution to the problem addressed by the program in its essence is not a pattern, by definition, although if it’s non-trivial you will ofte
Re: (Score:1)
Ordinary morality is for ordinary people. -- Aleister Crowley
Re: (Score:2)
CPAN modules are not pragmas (Score:1)
Re: (Score:1)
It hadn't occured to me yet and, in fact, I had to look for a pretty long time before I found the term "default module" in perlglossary for pragma. I think you mean that sentence. That was a fault on my part, so sorry for that.
But there seems to be oil all over the ocean already: autorequire [cpan.org], version [cpan.org] (will be ok then in 5.9 I guess), fake [cpan.org], all [cpan.org],
Ordinary morality is for ordinary people. -- Aleister Crowley
Re: (Score:1)
Re: (Score:1)
No worries, I'm not feeling singled out :) Though in my opinion it would have been more confusing to name it Namespace::Clean and affect the local package the way it does. I, and I had the impression that many others too, understand the term 'pragma' more as 'altering behaviour or environment' vs. the 'providing code' situation of library modules.
Ordinary morality is for ordinary people. -- Aleister Crowley
This is a bug (Score:1)
There's two related bugs here. If you localize or delete the stash a function exists in, the GV pointed to by the pp_gv opcode has a pointer to the original stash. This makes it oblivious to wholesale replacement of the stash.
It appears the other bug is that that the pp_gv opcode has a pointer to the GV and retain