I've rearranged the proposed features a bit to put the long objections at the bottom.
Brent Dax wrote: > I've been thinking about improvements that could be made to Exporter for > Perl 6. > 3. Warnings about conflicts: > use warnings 'Exporter'; > sub Dumper { ... } > use Data::Dumper qw(Dumper); > #prints out a warning (not just 'redefined subroutine', either). This would be nice. In fact, it could be retrofitted onto perl5's Exporter. > 4. For modules, saying 'use Exporter' should be enough to get import. > If you don't want Exporter's import(), just C<use Exporter()>. Very nice. Exporter::Lite does just that. > 5. In addition to @EXPORT/@EXPORT_OK/%EXPORT_TAGS, provide a way to do > it on the 'use Exporter' line. Getting rid of the @EXPORT* variables entirely would simplify both the interface and the internals. Exporter could then do a lot more caching and pre-calculating than it does now since it doesn't have to worry "Did they alter @EXPORT since the last time import() was called?" However, shoving everything onto the use line seems of somewhat dubious use. For starters, how do you say "don't export import()" and "export these variables please" at the same time? You start getting into special "dont_export" flags. Why not just a regular function or method? > > 1. Choosing where to export to: > use Data::Dumper 'Dumper' => 'dumpvar'; > #exports Data::Dumper::Dumper to Main::dumpvar (or whatever) > > 2. Built-in switch handling: > use Data::Dumper ('Dumper' : qw(+Indent=2 +Useqq)); > #imports Dumper, sets $Data::Dumper::Indent=2, and > # does $Data::Dumper::Useqq is true The above are both rare and of dubious practice. But that's not the real problem I have with it. What's the biggest problems with Exporter? 1) The man page is Big and Confusing to the first time module author. 2) Exporter is difficult to extend. 3) The internals are twisty and confusing. And they all stem from one issue: 4) Exporter tries to do too much already. The two biggest blocks to getting your first modules is figuring out Makefile.PL (and thus MakeMaker) and figuring out how to export functions. Both are confusing because the man pages are more reference than tutorial. They have to be references because the interfaces are big. The interfaces are big because they try to implement lots of features. They try to implement every feature because they're difficult to extend (ie. if you want to add to Exporter you have to rewrite Exporter). They're difficult to extend because it wasn't written to be extensible, there's lots of features, and in Exporter's case, it does backflips to try and be lightweight if you're only using a subset of its functionality (the Exporter::Heavy hack). Its interesting to look at who is using what bits of Exporter. Here's a very rough breakdown (crude scanner attached, all praise forwarded to Jeff Friedl). 1271 .pm files scanned 279 using or requiring Exporter 178 using anything beyond @EXPORT and @EXPORT_OK 125 anything beyond @EXPORT, @EXPORT_OK and %EXPORT_TAGS 83 using %EXPORT_TAGS 113 having their own import() 4 using @EXPORT_FAIL which shows a few interesting things: 1) Exporter isn't being used as much as I'd thought. 2) More people use %EXPORT_TAGS than I'd thought. 3) A lot more people are finding it necessary to write their own import() routine than I thought. 4) Almost nobody is using @EXPORT_FAIL (its just Carp and Exporter). So here's the priority list I'd write out for Exporter::NG: 1) Support functionality equivalent to @EXPORT, @EXPORT_OK and %EXPORT_TAGS and that's it. 2) Make the man page start with a quick tutorial. 3) Make it extensible. The important thing being that Perl 6's exporter has a small, simple, easy to explain interface. That it *doesn't* try to shove every feature into one namespace. And that its easy for people to write their own exporters. Then I'd look at those 113 modules that found it necessary to override Exporter's functionality (I've attached a list) and see what they're doing. Once you've got a handle on that, move to step four: 4) Write seperate extensions based on the above. -- Michael G. Schwern <[EMAIL PROTECTED]> http://www.pobox.com/~schwern/ Perl Quality Assurance <[EMAIL PROTECTED]> Kwalitee Is Job One This is my sig file. Is it not nify? Worship the sig file. http://www.sluggy.com
find /usr/local/share/perl/ /usr/share/perl*/ -name '*.pm' | wc -l find /usr/local/share/perl/ /usr/share/perl*/ -name '*.pm' | xargs perl -0777 -ne 'print "$ARGV\n" if /(use|require) Exporter/' | wc -l find /usr/local/share/perl/ /usr/share/perl*/ -name '*.pm' | xargs perl -0777 -ne ' $count++; if( /EXPORT_TAGS/ || /sub\s+import\b/ || /export_to_level/ || /EXPORT_FAIL/ || /export_tags/ || /export_ok_tags/ ) { $heavy_count++; print "$ARGV\n"; }' | wc -l find /usr/local/share/perl/ /usr/share/perl*/ -name '*.pm' | xargs perl -0777 -ne ' $count++; if( /sub\s+import\b/ || /export_to_level/ || /EXPORT_FAIL/ || /export_tags/ || /export_ok_tags/ ) { $heavy_count++; print "$ARGV\n"; }' | wc -l find /usr/local/share/perl/ /usr/share/perl*/ -name '*.pm' | xargs perl -0777 -ne ' $count++; if( /EXPORT_TAGS/ ) { $heavy_count++; print "$ARGV\n"; }' | wc -l find /usr/local/share/perl/ /usr/share/perl*/ -name '*.pm' | xargs perl -0777 -ne ' $count++; if( /sub\s+import\b/ ) { $heavy_count++; print "$ARGV\n"; }' | sort -n find /usr/local/share/perl/ /usr/share/perl*/ -name '*.pm' | xargs perl -0777 -ne ' $count++; if( /EXPORT_FAIL/ ) { $heavy_count++; print "$ARGV\n"; }' | wc -l
/usr/local/share/perl/5.6.0/Attribute/Types.pm /usr/local/share/perl/5.6.0/Parse/RecDescent.pm /usr/local/share/perl/5.6.0/UNIVERSAL/exports.pm /usr/local/share/perl/5.6.1/Acme/Buffy.pm /usr/local/share/perl/5.6.1/AnyData/Format/HTMLtable.pm /usr/local/share/perl/5.6.1/AnyData/Format/XML.pm /usr/local/share/perl/5.6.1/AnyLoader.pm /usr/local/share/perl/5.6.1/Attribute/Handlers.pm /usr/local/share/perl/5.6.1/CGI/Debug.pm /usr/local/share/perl/5.6.1/CPAN/Site.pm /usr/local/share/perl/5.6.1/Carp/Assert.pm /usr/local/share/perl/5.6.1/Class/Contract.pm /usr/local/share/perl/5.6.1/Class/Contract/Production.pm /usr/local/share/perl/5.6.1/Class/MethodMaker.pm /usr/local/share/perl/5.6.1/Class/Prototyped.pm /usr/local/share/perl/5.6.1/Convert/Units/Base.pm /usr/local/share/perl/5.6.1/Devel/SearchINC.pm /usr/local/share/perl/5.6.1/Error.pm /usr/local/share/perl/5.6.1/Exporter/Lite.pm /usr/local/share/perl/5.6.1/ExtUtils/AutoInstall.pm /usr/local/share/perl/5.6.1/Filter/Simple.pm /usr/local/share/perl/5.6.1/Getargs/Long.pm /usr/local/share/perl/5.6.1/Hook/LexWrap.pm /usr/local/share/perl/5.6.1/IO/LockedFile.pm /usr/local/share/perl/5.6.1/ImportTest.pm /usr/local/share/perl/5.6.1/Inline.pm /usr/local/share/perl/5.6.1/Inline/Java.pm /usr/local/share/perl/5.6.1/Inline/MakeMaker.pm /usr/local/share/perl/5.6.1/Lingua/Romana/Perligata.pm /usr/local/share/perl/5.6.1/Mail/Audit.pm /usr/local/share/perl/5.6.1/Mail/Field.pm /usr/local/share/perl/5.6.1/Mail/Mailer.pm /usr/local/share/perl/5.6.1/Math/BigFloat.pm /usr/local/share/perl/5.6.1/Math/BigInt.pm /usr/local/share/perl/5.6.1/Memoize/NDBM_File.pm /usr/local/share/perl/5.6.1/Memoize/SDBM_File.pm /usr/local/share/perl/5.6.1/Net/LDAP.pm /usr/local/share/perl/5.6.1/Net/LDAP/ASN.pm /usr/local/share/perl/5.6.1/Net/LDAP/Extra.pm /usr/local/share/perl/5.6.1/POE.pm /usr/local/share/perl/5.6.1/POE/Kernel.pm /usr/local/share/perl/5.6.1/POE/NFA.pm /usr/local/share/perl/5.6.1/POE/Preprocessor.pm /usr/local/share/perl/5.6.1/POE/Session.pm /usr/local/share/perl/5.6.1/Pod/Coverage.pm /usr/local/share/perl/5.6.1/Pollute.pm /usr/local/share/perl/5.6.1/Pollute/Persistent.pm /usr/local/share/perl/5.6.1/RTF/Group.pm /usr/local/share/perl/5.6.1/Switch.pm /usr/local/share/perl/5.6.1/Symbol/Approx/Sub.pm /usr/local/share/perl/5.6.1/Test/Builder.pm /usr/local/share/perl/5.6.1/Test/More.pm /usr/local/share/perl/5.6.1/Test/Simple.pm /usr/local/share/perl/5.6.1/YAPE/Regex.pm /usr/local/share/perl/5.6.1/uny2k.pm /usr/share/perl/5.6.0/private.pm /usr/share/perl/5.6.0/protected.pm /usr/share/perl/5.6.0/public.pm /usr/share/perl/5.6.1/AutoLoader.pm /usr/share/perl/5.6.1/CGI.pm /usr/share/perl/5.6.1/CGI/Carp.pm /usr/share/perl/5.6.1/Class/Struct.pm /usr/share/perl/5.6.1/English.pm /usr/share/perl/5.6.1/Env.pm /usr/share/perl/5.6.1/Exporter.pm /usr/share/perl/5.6.1/Fatal.pm /usr/share/perl/5.6.1/File/DosGlob.pm /usr/share/perl/5.6.1/File/stat.pm /usr/share/perl/5.6.1/FileHandle.pm /usr/share/perl/5.6.1/Getopt/Long.pm /usr/share/perl/5.6.1/Math/BigInt.pm /usr/share/perl/5.6.1/Net/hostent.pm /usr/share/perl/5.6.1/Net/netent.pm /usr/share/perl/5.6.1/Net/protoent.pm /usr/share/perl/5.6.1/Net/servent.pm /usr/share/perl/5.6.1/Shell.pm /usr/share/perl/5.6.1/User/grent.pm /usr/share/perl/5.6.1/User/pwent.pm /usr/share/perl/5.6.1/attributes.pm /usr/share/perl/5.6.1/autouse.pm /usr/share/perl/5.6.1/base.pm /usr/share/perl/5.6.1/blib.pm /usr/share/perl/5.6.1/bytes.pm /usr/share/perl/5.6.1/charnames.pm /usr/share/perl/5.6.1/constant.pm /usr/share/perl/5.6.1/diagnostics.pm /usr/share/perl/5.6.1/fields.pm /usr/share/perl/5.6.1/filetest.pm /usr/share/perl/5.6.1/integer.pm /usr/share/perl/5.6.1/lib.pm /usr/share/perl/5.6.1/locale.pm /usr/share/perl/5.6.1/open.pm /usr/share/perl/5.6.1/overload.pm /usr/share/perl/5.6.1/private.pm /usr/share/perl/5.6.1/protected.pm /usr/share/perl/5.6.1/public.pm /usr/share/perl/5.6.1/sigtrap.pm /usr/share/perl/5.6.1/strict.pm /usr/share/perl/5.6.1/subs.pm /usr/share/perl/5.6.1/utf8.pm /usr/share/perl/5.6.1/vars.pm /usr/share/perl/5.6.1/warnings.pm /usr/share/perl/5.6.1/warnings/register.pm /usr/share/perl5/CGI.pm /usr/share/perl5/CGI/Carp.pm /usr/share/perl5/Debconf/Client/ConfModule.pm /usr/share/perl5/Debian/DebConf/Client/ConfModule.pm /usr/share/perl5/Debian/Debhelper/Dh_Getopt.pm /usr/share/perl5/LWP/Debug.pm /usr/share/perl5/LWP/Simple.pm /usr/share/perl5/MLDBM.pm /usr/share/perl5/Mail/Field.pm /usr/share/perl5/Mail/Mailer.pm