=encoding utf-8 =pod =head1 Using use =head2 META =head3 Author Thomas Klausner =head3 Email domm AT cpan.at =head3 URL http://domm.zsi.at =head3 URL_slides http://domm.zsi.at/talks/2005_braga_using_use =head3 Date 2005-09-01 =head3 Location Braga, Protugal =head3 Event YAPC::Europe 2005 =head2 Intro We use C a lot: use 5.8.0; use Data::Dumper; use strict; use Template 2.14; use CGI ':cgi'; use base qw(Class::DBI); During the next 40 minutes, we'll take a very close look at C. =head3 Compile Time vs. Run Time Everybody knows the difference? C is run at Compile Time As soon as C is discovered while reading code, it's executed: =for include_and_run examples/001_timing.pl B is not printed. The code C. =for newslide This is more obvious in this example: =for include_and_run examples/002_if.pl Even though the code shouldn't be run at all, Perl tries to load Nonexisting::Module. And fails. =for newslide B C is run at Compile Time, not at Run Time. More on this later... =head2 use VERSION; use 5.8.0; The program requires this or a higher version of Perl. =for include_code examples/003_version.pl C didn't work prior to 5.8.0. Instead of running with a buggy version, we just stop. =for newslide =for include_and_run examples/004_version.pl =head2 use Module; use Data::Dumper; Loads the module C But how? =head3 Conversion Module-Name - Filename First we need a filename. For that purpose the C<::> are converted to C. And C<.pm> is appended. In fact, those steps are taken by C, But this is not the topic of this talk... C gets C. =head3 %INC Now Perl checks if this module was loaded already. This is the job of C<%INC>. C<%INC> stores the B as C and the B as C: =for include_and_run examples/005_hash_inc.pl =for newslide If a filename is already stored in C<%INC>, the module won't get loaded again. =for include_code examples/HashIncOften.pm =for include_and_run examples/006_hash_inc_often.pl The module C is loaded only once, even though it's called four times. =head3 @INC But where from are the modules loaded? Now C<@INC> joins the the game. C<@INC> contains absolute paths to places where modules can be stored. ~/$ perl -V ... @INC: /usr/local/lib/perl5/5.8.5/i686-linux-multi /usr/local/lib/perl5/5.8.5 /usr/local/lib/perl5/site_perl/5.8.5/i686-linux-multi /usr/local/lib/perl5/site_perl/5.8.5 /usr/local/lib/perl5/site_perl . =for newslide If we take another look at the previous example: =for include_and_run examples/005_hash_inc.pl We can see the C is stored in the file **/usr/local/lib/perl5/site_perl/5.8.5/**%%Class/Accessor.pm%% =for newslide B The current working directory "B<.>" is also part of C<@INC>. Given this directory structure: twop/ teeoo.pl Glont.pm =for include_code examples/twop/teeoo.pl =for include_code examples/twop/Glont.pm =for newslide The following works: =for run_code examples/twop/teeoo.pl But this does not: ~/examples$ perl twop/teeoo.pl Can't locate Glont.pm in @INC (@INC contains ...) at twop/teeoo.pl line 1. Why? Because C is not in C<.> in the second example. =head3 Modifying @INC Luckily, C<@INC> is not... =for img han_solo.jpg frozen! =head4 $ENV{PERL5LIB} The environment variable C (or C) can contain colon-seperated directory names. Which will be search prior to C<@INC>. export PERL5LIB=/shlorp:/spoosht But I don't like environment variables. So you'll have to read on your own: C =head4 push(@INC,'dir'); C<@INC> is just another array. So you can C arbitray paths onto C<@INC>. push(@INC,'splap'); But this doesn't work that well: examples/ 007_push_inc.pl splap/ PushInc.pm =for newslide =for include_code examples/splap/PushInc.pm =for include_and_run examples/007_push_inc.pl Why ... ? =for newslide Because C is run at Compile Time, but C only at Run Time. Which means that when C is called, C<@INC> hasn't been modified. =head4 BEGIN { push(@INC,'dir') } One solution: a BEGIN block =for include_and_run examples/008_push_inc_begin.pl But there are more beautifull ways... =head4 use lib 'dir'; C is part of Perl since C. It simplifies the manipulation of C<@INC>. =for include_and_run examples/009_use_lib.pl C ist the recommended way to alter C<@INC>. =for newslide C has some more features: =over =item * remove dirs from C<@INC> no lib 'toonk'; =item * Restore original C<@INC> @lib::ORIG_INC; =back More info in C. But there are times when C isn't flexible enough... =head4 FindBin C is also part of Perl since C. C locates the directory in which the running script is stored. =for include_and_run examples/010_findbin.pl This isn't that impressive by itself, but in combination with C we can solve the problem we had earlier. =for newslide twop/ teeoo_findbin.pl Glont.pm =for include_code examples/twop/teeoo_findbin.pl ~/examples$ perl twop/teeoo_findbin.pl loading Glont ok =for newslide C and are very handy if you need to deploy scripts and modules in environments you have not much control over. Glorkle/ bin/ ding.pl plortch.pl lib/ Glorkle.pm Glorkle/ Wunkada.pm Garoof.pm The scrips in C need the modules in C. The application will not be properly installed (using Makefile.PL / Build.PL) The tarball will be extracted somewhere and things should work. =for newslide file: Glorkle/bin/ding.pl use FindBin; use lib "$FindBin::Bin/../lib"; use Glorkle; ... But it's even easier... =head4 rlib C is available from CPAN http://search.cpan.org/dist/rlib C works like C, but it treats paths as relative to the location of the file it was called in. =for include_code examples/twop/teeoo_rlib.pl ~/examples$ perl twop/teeoo_rlib.pl loading Glont ok =head4 Uff Now that we know where modules are loaded from we take a close look what happens during loading. Therefore we must examine the second parameter passed to C. =head2 use Module VERSION; If it's a version number the $VERSION of the module beeing loaded is compared with the parameter. The module is only loaded if the installed version is recent enough. But that's not that interesting. IMO... =head2 use Module qw(blop); After module name to file name conversion, locating the file in C<@INC>, and reading and parsing the code, Perl calls the C function of the module beeing loaded. If a module hasn't got an C function, the call is skipped. =head3 import Let's try that: =for include_code examples/Skapasch.pm =for include_and_run examples/011_import.pl Great! =head3 suppressing import To prevent C from beeing called, pass in an empty list: =for include_and_run examples/012_no_import.pl =head3 Why import? A lot of modules export symbols (variables, subroutines, ..) into the 'calling namespace'. That's one of the main ideas of functional programming: =over =item * Functions are defined in reusable modules (libraries). =item * Needed functions are imported on demand. =back =head4 Example =for include_and_run examples/013_datadumper_1.pl =for newslide =for include_and_run examples/014_datadumper_2.pl The function C (defined in C) cannot be called because importing was suppressedby the empty list. =head3 Exporter As this is Perl, you rarely have to write C functions on your own. There are serveral modules that invented that wheel: Exporter Exporter::Cluster Exporter::Dispatch Exporter::Easy Exporter::Lite Exporter::NoWork Exporter::Renaming Exporter::Simple Exporter::Tidy Exporter::VA Class::Exporter Let's start with C, Perl core since 5.003007. =head4 Exporter =for include_code examples/Groon.pm =for newslide =for include_and_run examples/015_exporter.pl =for newslide =for include_and_run examples/016_exporter.pl =for newslide =for include_and_run examples/017_exporter.pl =for newslide C is used by a lot of modules. 3482 according to CPANTS. It has got several other features. eg. Import lists (C) perldoc Exporter =for newslide But there are several drawbacks, especially the complex setup: =over =item * You need to subclass it. =item * You need global variables =item * You have to list the symbols to be exported by hand (DRY!) =back =for newslide To tell you the truth, you can use C without subclassing: package YourModule; use Exporter qw( import ); By importing its C function. =head4 Exporter::Lite C is another way to avoide the subclassing =for include_code examples/Groon2.pm =for newslide =for include_and_run examples/018_exporter_lite.pl C achieves this by something called B. More on that later. =head4 Exporter::Tidy Another Exporter with a slightly different syntax. And without global variables. =for include_code examples/Groon3.pm =for newslide =for include_and_run examples/019_exporter_tidy.pl The interesting point here is that C doesn't get a simple list as a second parameter, but a complex data structure. =for newslide C has some additional nice features like: _prefix =for include_and_run examples/020_exporter_tidy.pl =head4 Exporter::Simple C works around the double listing of symbol names (once in the code and once in the export-definition) Drawback: You need to subclass it. =for include_code examples/Groon4.pm =for newslide =for include_and_run examples/021_exporter_simple.pl This works by using attributes (C<:Exported>, C<:Exportable>) Which is similar to the Perl 6 way. =for newslide Let's stop with the ready-made Exporters and take a closer look at C =head3 import 2 parameters are passed to C =over =item * the name of the called namespace =item * the import list =back =for include_code examples/Barramm.pm =for newslide =for include_and_run examples/022_import.pl To turn this into something usefull, we need one more building block: =head4 caller In scalar context, C returns the name of the calling package. In list context, C returns a lot more, but we're not interested in it right now. (If you're interested: C) =for newslide =for include_code examples/Barramm2.pm =for include_and_run examples/023_import.pl Ok, now we can build something usefull. Ahm, limited usefull ... =head4 Limited usefull example =for include_code examples/Zat.pm *{**"$caller\::zat"**}=\%%&do_zat%%; # Typeglob! =for include_and_run examples/024_zat.pl =head4 Now the fun starts! As soon as you realise that you can run B Perl code in C the fun starts! =head4 Code Generation =for include_code examples/Gorshle.pm If we say C from a package C, the generated code looks like this: package **Waak**::Gorshle; use base 'Gorshle'; sub %%waak%% { return '**Waak**' } =for newslide =for include_and_run examples/025_gorshle.pl We dynamically generate a new class by simply saying C. The exact definition of this generated class depeneds on the class that Cd C =head4 Parameter Munging =for include_code examples/Sreek.pm my $singleton=bless {**@_**},$package; **$**{"%%$caller\::singleton%%"}=$singleton; =for newslide =for include_and_run examples/026_sreek.pl C is loaded with various parameters. C<$singleton> appears out of nothing. You can get to the parameters via C<< $singleton->get() >>. =head4 Mixins With mixins you can extend classes by other ways as subclassing. This is especially handy when using complex class hierarchies. Which is why the following example might be a bit to If you ever had to fight with multiple inheritance ans especially diamond inheritance you should really look at mixins. http://c2.com/cgi/wiki?MixIn =for newslide =for include_code examples/Twop.pm We export the function C Which takes an object and dumps it using C. =for newslide =for include_code examples/027_twop.pl First we define a package C, And C in it. Back in C
we initiate an object of this class. And call C on it. =for newslide =for run_code examples/027_twop.pl C was exported from C into C. Or rather B. =head4 Apropos Krunch, Twop, etc Did anybody wonderd what does strange class names mean? Does anybody know C? =head3 Acme::MetaSyntactic (by BooK) C fights boring test values like C and C! C provides an great number of thematically grouped variable names. C also has an very interesting C function. We'll take a close look at it soon. =for newslide BTW, I'm using C =for img donmartin.jpg =head4 Usage (from the SYNOPSIS) =for include_and_run examples/028_ams.pl It seems that a function called C is exported. =for newslide =for include_and_run examples/029_ams.pl Now nothing is imported. C is now used in an object oriented way. =for newslide =for include_and_run examples/030_ams.pl Now it's getting interesting.. C is exported as previously. But additionally the function C and C are exported. Those functions seem to depend on the import list C. =for newslide You can even use C from the command line: ~/$ perl -MAcme::MetaSyntactic=batman -le 'print metaname' crash C<-M> loads the module. C<=batman> is converted to C and C is passed as an parameter to C. More info: C C<-M>. =for newslide That's the way I generated all package-, script, and variable-names: ~/$ perl -MAcme::MetaSyntactic=donmartin -le 'print metaname' gadink OK, and now we'll look at Cs C. =head4 Acme::MetaSyntactic's import sub import { my $class = shift; my @themes = ( grep { $_ eq ':all' } @_ ) ? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first : @_; $Theme = $themes[0] if @themes; $meta = Acme::MetaSyntactic->new( $Theme ); # export the metaname() function no strict 'refs'; my $callpkg = caller; *{"$callpkg\::metaname"} = \&metaname; # standard theme # load the classes in @themes for my $theme( @themes ) { eval "require Acme::MetaSyntactic::$theme;"; croak $@ if $@; *{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; } } Before we can actually take a closer look, we need to see even more code =for newslide our $Theme = 'foo'; # default theme our %META; # fetch the list of standard themes { my @themes; for my $dir (@INC) { $META{$_} = 0 for grep !/^[A-Z]/, # remove the non-theme subclasses map { ( fileparse( $_, qr/\.pm$/ ) )[0] } File::Glob::bsd_glob( File::Spec->catfile( $dir, qw( Acme MetaSyntactic *.pm ) ) ); } } # the functions actually hide an instance my $meta = Acme::MetaSyntactic->new( $Theme ); sub import { ... This code is run at while C is loaded. =for newslide **our $Theme = 'foo';** # default theme our %META; # fetch the list of standard themes { my @themes; for my $dir (@INC) { $META{$_} = 0 for grep !/^[A-Z]/, # remove the non-theme subclasses map { ( fileparse( $_, qr/\.pm$/ ) )[0] } File::Glob::bsd_glob( File::Spec->catfile( $dir, qw( Acme MetaSyntactic *.pm ) ) ); } } # the functions actually hide an instance my $meta = Acme::MetaSyntactic->new( $Theme ); sub import { ... =for newslide our $Theme = 'foo'; # default theme our **%META**; # fetch the list of standard themes { my @themes; for my $dir (@INC) { $META{$_} = 0 for grep !/^[A-Z]/, # remove the non-theme subclasses map { ( fileparse( $_, qr/\.pm$/ ) )[0] } File::Glob::bsd_glob( File::Spec->catfile( $dir, qw( Acme MetaSyntactic *.pm ) ) ); } } # the functions actually hide an instance my $meta = Acme::MetaSyntactic->new( $Theme ); sub import { ... =for newslide our $Theme = 'foo'; # default theme our **%META**; # fetch the list of standard themes { my @themes; for my $dir (@INC) { **$META{$_}** = 0 for %%grep !/^[A-Z]/,%% # remove the non-theme subclasses %%map { ( fileparse( $_, qr/\.pm$/ ) )[0] } File::Glob::bsd_glob( File::Spec->catfile( $dir, qw( Acme MetaSyntactic *.pm ) ) )%%; } } # the functions actually hide an instance my $meta = Acme::MetaSyntactic->new( $Theme ); sub import { ... C<%META> contains a list of all available themes (eg 'donmartin', 'batman') You can query C<%META> by calling C. ~/$ perl -MAcme::MetaSyntactic -le 'print for Acme::MetaSyntactic->themes' =for newslide alphabet amber any batman browser buffy crypto dancers debian dilbert donmartin elements flintstones foo haddock hhgg jamesbond loremipsum magic8ball phonetic pumpkings pynchon python quantum robin shadok teletubbies tld toto viclones =for newslide our %%$Theme = 'foo'%%; # default theme our %META; # fetch the list of standard themes { my @themes; for my $dir (@INC) { $META{$_} = 0 for grep !/^[A-Z]/, # remove the non-theme subclasses map { ( fileparse( $_, qr/\.pm$/ ) )[0] } File::Glob::bsd_glob( File::Spec->catfile( $dir, qw( Acme MetaSyntactic *.pm ) ) ); } } # the functions actually hide an instance **my $meta = Acme::MetaSyntactic->new**( %%$Theme%% ); sub import { ... An object is initated. And now for C. =for newslide sub import { my $class = shift; my **@themes** = ( %%grep { $_ eq ':all' } @_%% ) ? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first : @_; $Theme = $themes[0] if @themes; $meta = Acme::MetaSyntactic->new( $Theme ); # export the metaname() function no strict 'refs'; my $callpkg = caller; *{"$callpkg\::metaname"} = \&metaname; # standard theme # load the classes in @themes for my $theme( @themes ) { eval "require Acme::MetaSyntactic::$theme;"; croak $@ if $@; *{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; } } BooK starts with paramater handling. If you say C =for newslide sub import { my $class = shift; my **@themes** = ( grep { $_ eq ':all' } @_ ) ? ( %%'foo', grep { !/^(?:foo|:all)$/ } keys %META%% ) # 'foo' is still first : @_; $Theme = $themes[0] if @themes; $meta = Acme::MetaSyntactic->new( $Theme ); # export the metaname() function no strict 'refs'; my $callpkg = caller; *{"$callpkg\::metaname"} = \&metaname; # standard theme # load the classes in @themes for my $theme( @themes ) { eval "require Acme::MetaSyntactic::$theme;"; croak $@ if $@; *{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; } } All available themes are used. With C beeing the first and default one. =for newslide sub import { my $class = shift; my **@themes** = ( grep { $_ eq ':all' } @_ ) ? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first : %%@_%%; $Theme = $themes[0] if @themes; $meta = Acme::MetaSyntactic->new( $Theme ); # export the metaname() function no strict 'refs'; my $callpkg = caller; *{"$callpkg\::metaname"} = \&metaname; # standard theme # load the classes in @themes for my $theme( @themes ) { eval "require Acme::MetaSyntactic::$theme;"; croak $@ if $@; *{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; } } If you B pass C the passed list of themes is used. eg: C =for newslide sub import { my $class = shift; my @themes = ( grep { $_ eq ':all' } @_ ) ? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first : @_; **$Theme = $themes[0]** if @themes; $meta = Acme::MetaSyntactic->new( $Theme ); # export the metaname() function no strict 'refs'; my $callpkg = caller; *{"$callpkg\::metaname"} = \&metaname; # standard theme # load the classes in @themes for my $theme( @themes ) { eval "require Acme::MetaSyntactic::$theme;"; croak $@ if $@; *{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; } } The package-global C<$Theme> is set to the first element of C<@themes>. =for newslide sub import { my $class = shift; my @themes = ( grep { $_ eq ':all' } @_ ) ? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first : @_; $Theme = $themes[0] if @themes; **$meta = Acme::MetaSyntactic->new**( %%$Theme%% ); # export the metaname() function no strict 'refs'; my $callpkg = caller; *{"$callpkg\::metaname"} = \&metaname; # standard theme # load the classes in @themes for my $theme( @themes ) { eval "require Acme::MetaSyntactic::$theme;"; croak $@ if $@; *{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; } } Another object is initiated (with the according default C<$Theme>). =for newslide sub import { my $class = shift; my @themes = ( grep { $_ eq ':all' } @_ ) ? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first : @_; $Theme = $themes[0] if @themes; $meta = Acme::MetaSyntactic->new( $Theme ); # export the metaname() function @@no strict 'refs';@@ %%my $callpkg = caller;%% ***{"$callpkg\::metaname"} = \&metaname;** # standard theme # load the classes in @themes for my $theme( @themes ) { eval "require Acme::MetaSyntactic::$theme;"; croak $@ if $@; *{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; } } The function C handling the default theme (C<$Theme respectivly $themes[0]>) is exported. =for newslide sub import { my $class = shift; my @themes = ( grep { $_ eq ':all' } @_ ) ? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first : @_; $Theme = $themes[0] if @themes; $meta = Acme::MetaSyntactic->new( $Theme ); # export the metaname() function no strict 'refs'; my $callpkg = caller; *{"$callpkg\::metaname"} = \&metaname; # standard theme # load the classes in @themes **for my $theme( @themes )** { eval "**require Acme::MetaSyntactic::$theme;**"; croak $@ if $@; *{"$callpkg\::meta$theme"} = sub { $meta->name( $theme, @_ ) }; } } =for newslide sub import { my $class = shift; my @themes = ( grep { $_ eq ':all' } @_ ) ? ( 'foo', grep { !/^(?:foo|:all)$/ } keys %META ) # 'foo' is still first : @_; $Theme = $themes[0] if @themes; $meta = Acme::MetaSyntactic->new( $Theme ); # export the metaname() function no strict 'refs'; my $callpkg = caller; *{"$callpkg\::metaname"} = \&metaname; # standard theme # load the classes in @themes for my $theme( @themes ) { eval "require Acme::MetaSyntactic::$theme;"; croak $@ if $@; *{"$callpkg\::**meta**%%$theme%%"} = sub { @@$meta@@->**name**( %%$theme%%, @_ ) }; } } For all other themes an accessor named after the theme is exported. Which is only a thin wrapper around C. =for newslide C shows how you can write a module that's very easy to use in a lot of different ways by writing a clever C function. =head2 Résumé You can achieve some very interesting effects if you write your own import functions. =head2 Questions?