Re: use Very::Long::Module::Name as Foo;
by tilly (Archbishop) on Oct 14, 2003 at 14:18 UTC
|
Sorry, but I prefer the existing solutions.
In terms of complexity to use, all of the proposed solutions, including yours, are about equal. In terms of conceptual difficulty for a Perl programmer to figure out how they work under the hood, yours is significantly more complicated. In terms of avoiding possible conflicts between different modules making use of the feature, I prefer either putting the package name in a variable or a constant to anything that tramples over short global namespaces that other modules don't expect you to trample over.
Also I like reserving source filtering for when it really buys a lot because I am afraid that, going forward, we will wind up with "interesting conflicts" because different source filters won't cooperate well with each other. (The heuristics which one uses to figure out what is going on don't take into account how the previous one altered Perl.) Traditional Perl modules have much lower odds of conflict.
In fact a private theory of mine holds that one of the keys to what made CPAN work is that Perl didn't used to lend itself to customization, so code that worked for you probably works without many issues in my environment, and vice versa. This makes sharing easy. Compare, say, to a significant body of C code with heavy use of pre-processor definitions. | [reply] [Watch: Dir/Any] |
|
use Very::Long::Module::Name as Foo;
is definitely easier to type and to the eye than:
use as qw(Very::Long::Module::Name Foo); # Package Alias approach
especially when it comes to parametrized uses. These would all work with my source filter:
use Very::Long::Module::Name as Foo qw(foo bar baz); # import foo, bar
+ baz
use Very::Long::Module::Name as Foo (); # don't import
Package::Alias (and Abigail's approach) does not support this.
...conceptual difficulty for a Perl programmer to figure out how they work under the hood...
I also disagree here. If you know about source filters, you will see that the filter is very simple. Creating the source filter involves some strange idioms, I agree, but I can't be blamed for that. And adding some more comments should take care of instructing any other Perl programmers who take a look under the hood.
Traditional Perl modules have much lower odds of conflict.
I agree. But I see the source filter merely as a means of achieving the end now, as a prototyping tool, rather than as the way to do such a thing in the long run.
And so far nobody has commented on the API. So that at least feels right to the people who looked at this so far. I don't think there is a Perl 6 Apocalypse about this, is there?
Liz | [reply] [Watch: Dir/Any] [d/l] [select] |
|
package load;
use Carp;
use strict;
sub as {
my $pkg = shift;
# Set the alias.
$_[0] = $pkg;
# load the module
eval "require $pkg";
die $@ if $@;
# import it?
shift;
if (@_) {
unshift @_, $pkg;
my $import = $pkg->can("import")
or croak("No import available to use");
goto &$import;
}
}
1;
This can now be used (assuming no bugs...) as follows:
use load;
Very::Long::Module->load::as my $short => qw(foo bar baz);
If you prefer a constant approach, that isn't hard to do either.
In any case the difference in ease of usage between these solutions and a source filter is pretty minor. The difference in potential problems is pretty large. (Note that I am steering towards solutions where you can create any aliases for yourself without trampling on any potential global namespace. That is both deliberate and, I feel, important.) | [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
|
|
|
Re: use Very::Long::Module::Name as Foo;
by demerphq (Chancellor) on Oct 14, 2003 at 14:31 UTC
|
IMO source filters are a bad idea. My choices for resolving this in an external module would be (in order of preference):
use Some::Very::Long::And::Annoying::Package::Name;
use constant SVLAAPN=>'Some::Very::Long::And::Annoying::Package::Name'
+;
push @SVLAAPN::ISA,'Some::Very::Long::And::Annoying::Package::Name';
my $o=SVLAAPN->new();
Its unlikely I would use the stash approach as that just gives me the heebie-jeebies.
But this comes to an interesting point. An author of such an annoying package can easily provide the alias themselves... Ie in perl/site/lib/Some/Very/Long/And/Annoying/Package/Name.pm the author could have easily put
package SVLAAPN;
...
IOW, the package contained in a file that is used need _not_ be the same as the filename would indicate. A good and common example is Carp::Heavy. There is in fact no such thing. The file perl/lib/Carp/Heavy.pm contains only code for the package Carp. Now this might not be the best example as Carp/Heavy.pm is a behind the scenes kinda thing, but it does illustrate the point nicely.
In short while this is groovy and cool looking, it isn't perl (really), and it doesnt belong in production code. Nor do I think there is much need for this type of thing. The problem doesnt arise much and it only takes a few lines of code to sort out when it does. So IMO, this is a bit of overkill.
---
demerphq
First they ignore you, then they laugh at you, then they fight you, then you win.
-- Gandhi
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: use Very::Long::Module::Name as Foo;
by Abigail-II (Bishop) on Oct 14, 2003 at 14:40 UTC
|
Here's a different way, also using a 'as.pm', but no source
filters. Usage:
use as Name => "Very::Long::Class::Name", args ...;
And this is the code:
package as;
use strict;
use warnings;
sub import {
my $class = shift;
die "Usage: 'use as Name => Very::Long::Class::Name [args...]'"
unless @_ >= 2;
my $caller = caller ();
my ($short, $long) = splice @_ => 0, 2;
no strict 'refs';
@{"${short}::ISA"} = $long;
eval <<" --";
package $caller;
require $long;
$short -> import (\@_) if $short -> can ("import");
--
die $@ if $@;
}
1;
This follows a similar syntax as 'use if CONDITION, MODULE => ARGS'.
Abigail | [reply] [Watch: Dir/Any] [d/l] [select] |
|
This is essentially the same API as Package::Alias, although different under the hood.
Liz
| [reply] [Watch: Dir/Any] |
Re: use Very::Long::Module::Name as Foo;
by broquaint (Abbot) on Oct 14, 2003 at 14:36 UTC
|
The problem with a source filter approach is that it can very easily run over program data or conflict with existing filters. Personally, I would've thought a straight-forward import approach would've been easiest e.g
package allow_as;
use Carp 'croak';
sub import {
my($pkg, %args) = @_;
return
unless exists $args{as} and length $args{as};
croak "Symbol table '$args{as}' already exists"
if defined *{"$args{as}\::"};
*{"$args{as}\::"} = *{"$pkg\::"};
}
1;
=pod
=head1 USAGE
package Your::Very::Long::Name::Here;
use base 'allow_as';
sub import {
## perhaps you want your own import code?
$_[0]->SUPER::import(@_[1 .. $#_]);
}
## later
use Your::Very::Long::Name::Here (
as => 'yvlnh',
other => [qw/user parameters perhaps?/],
);
=cut
This doesn't work as globally as your filtering mechanism, but it also follows in the footsteps of Exporter of allowing the user to simply inherit the module to enable aliasing (which may not always be desirable, like the ability to export random methods). Also, the reason I stuck with the aliasing route is that it is much cleaner than simply using @ISA. It means that objects are blessed into the original package and not the inherited alias, which will keep any introspection consistent, saves avoids dispatching every method call, and it really is an alias as opposed to a quick work-around.
| [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] [d/l] |
|
Method calls are cached so it makes no difference what package they are called against.
Ah yes, I'm forever forgetting that!
And the constant-or-variable-with-package-name-in-it approach has the same properties as your code FWICT.
But it's not an alias, it's just a shorter way of referring to a package name (although this does equate to the same thing when calling class methods). It means the difference between referring symbolically to the original package, and referring to the package directly via the alias e.g
## accessing a package variable
my $path = ${"$var\::Config"}->{'data_path'};
## vs.
my $path = $alias::Config->{'data_path'};
Ok, so it might be a somewhat contrived, but I think it nicely illustrates that the two approaches are not the same.
| [reply] [Watch: Dir/Any] [d/l] |
Re: use Very::Long::Module::Name as Foo;
by hardburn (Abbot) on Oct 14, 2003 at 16:59 UTC
|
. . . bart's response (which is the simple assignment of @ISA) . . .
I'd like to use this as cannon fodder against those who said modifying @ISA directly is OK here. My argument in that meditation was that directly assigning @ISA is bad because it clobbers any existing values, and that one should always use base instead, if possible. Many posters in that thread noted that nobody else should be messing with your package's @ISA. At the time, I couldn't come up with a good reason why an external source would be playing with your @ISA, but thought there might be a good reason that I hadn't seen yet. Now I have one. Thanks :)
I'd like to take this opertunity to say na na na, your it, no returns.
---- I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
-- Schemer
Note: All code is untested, unless otherwise stated
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: use Very::Long::Module::Name as Foo;
by pg (Canon) on Oct 14, 2003 at 15:20 UTC
|
I realized something…
The real problem is that Perl does not differentiate the concept of ‘package’ and the ‘class’ being contained in the ‘package’. Otherwise, you should not worry to mention the full path of the package, as long as the class name only exists in a single package that you loaded.
I would expect this go on the right track, once OO is supported in a more natural way in Perl…
| [reply] [Watch: Dir/Any] |
Re: use Very::Long::Module::Name as Foo;
by pg (Canon) on Oct 14, 2003 at 14:36 UTC
|
I think those solutions provided previously are good enough for now. Although personally I believe, it makes much more sense for Perl to deliver this kind of trivial but essential stuffs as part of the language itself (not as any sort of patch). | [reply] [Watch: Dir/Any] |
|
...it makes much more sense for Perl to deliver this kind of trivial but essential stuffs as part of the language itself...
I couldn't agree more. But suppose I would find the courage to go into the Perl innards so that this would be possible in 5.10. Wouldn't it then be nice to be able to use that idiom in older versions of Perl as well?
And vice versa, the "public acceptance" of this module would be a good indication of whether it would make sense to put such a feature in the core Perl itself.
Liz
| [reply] [Watch: Dir/Any] |
Re: use Very::Long::Module::Name as Foo;
by Aristotle (Chancellor) on Oct 15, 2003 at 00:09 UTC
|
Your approach isn't transparent: references will be blessed into the shortname package. I chose to use constants in the other thread for this reason.
$ perl -MO=Deparse -e'Foo::Bar->new'
'Foo::Bar'->new;
-e syntax OK
$ perl -MO=Deparse -e'use constant FB => "Foo::Bar"; FB->new'
use constant ('FB', 'Foo::Bar');
'Foo::Bar'->new;
-e syntax OK
Note how it compiles to exactly the same code. There is absolutely no chance that it will behave any differently than the original code in any case ever.
And while it may seem simple, your approach needs some very heavy weaponry to work. It is in gross violation of the "do the simplest thing that can possibly work" principle.
Makeshifts last the longest.
| [reply] [Watch: Dir/Any] |
|
As I try not to use indirect object syntax (anymore), I think the approach to define a constant is the most portable way for now. So no argument from me there (anymore).
It is in gross violation of the "do the simplest thing that can possibly work" principle.
I don't agree there. I still think my approach is the cleanest from the user's point of view. It doesn't need the definition of any extra variables or constants, which I think are cruft from an API point of view. And therefore, it is the simplest thing that can possibly work in my eyes.
Under the hood, Perl is already using rather heavy weaponry to DWIM. Constants are one (first create a subroutine, then inline the constant later). Tieing variables is another one. And what about $&? All can be done in other ways, yet everyone likes the fact that they're there if they want to take the performance penalty.
Personally, I think it would not be a real big issue to implement the "as modulename" feature in the C-code that handles "use" in Perl (which would put the namespace aliasing stuff under the hood there). And I think the effect on compiling would be negligeble (only extra complexity while compiling a "use"). However, the reason I'm not going to pursue this, is the global namespace problem. I don't see a simple solution for making the short name local to the package in which it "defined".
Liz
| [reply] [Watch: Dir/Any] |
|
Your approach isn't transparent: references will be blessed into the shortname package.
shell> perl -le '*a::=*b::; print bless [], "a"'
b=ARRAY(0x8107f70)
Or not. As we can see, a is really just like any other glob alias and so is completely transparent.
| [reply] [Watch: Dir/Any] [d/l] |