Re: Perl 6's Exporter

2001-12-22 Thread Michael G Schwern

On Sat, Dec 22, 2001 at 09:20:08PM -0800, Brent Dax wrote:
> # 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.
> 
> Huh?

If you have to do this:

use Exporter (
export => ...
);

how do you also do this:

use Exporter ();

you're making Exporter::import do double-duty.

As an example of this thing being troublesome, Test::More's interface
was originally just this:

use Test::More tests => 42;

but it also exports a whole bunch of functions.  Somebody wanted to
control what functions it exports.  Normally it would be something
like:

use Test::More qw(is ok);

but then how do you say how many tests you're going to run?  You
don't.  I had to add in 'import' key:

use Test::More tests => 42, import => [qw(is ok)];

if I had it to do over again, I would have done the 'use' and the
'tests' as seperate statements.


> # Why not just a regular function or method?
> 
> I like the idea of just dealing with Exporter in one statement and then
> forgetting it even exists.  

"Sure you can do it in one line.  Is it ok if that line is 240
characters long?"  

> To me, something like:
> 
>   use Exporter;
>   our $Exp=new Exporter;
>   $Exp.default=qw(foo bar);
>   $Exp.ok=qw(baz quux);
>   $Exp.tags=(':B' => [qw(bar baz)]);
> 
> is little better than:
> 
>   use Exporter;
>   our @ISA='Exporter';
>   our @EXPORT=qw(foo bar);
>   our @EXPORT_OK=qw(baz quux);
>   our %EXPORT_TAGS=(':B' => [qw(bar baz)]);
> 
> A little less typing, perhaps, but still too much for my tastes.

I was thinking something more like:

use Exporter;
Exporter.export(qw(foo bar));
Exporter.ok(qw(baz quux));
Exporter.tags( B => [qw(bar baz)] );

or perhaps something in between:

use Exporter;
Exporter.export(
export  => [qw(foo bar)],
ok  => [qw(baz quux)],
tags=> { B => [qw(bar baz)]
);

which is very close to yours:

use Exporter (
export => [qw(foo bar)],
ok => [qw(baz quux)],
tags   => { B => [qw(bar baz)]
);

only it leaves Exporter's import() routine open to handle Exporter's
own exports.


> # > 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
> 
> I disagree.  The first one is something I thought of because of the
> p5p 'exporting considered harmful' thread (i.e. importing 'Dumper'
> to something more sensible); the second one is something many
> modules implement hacks to do.  (Carp and CGI both do it in some
> way; Data::Dumper, Test::(More|Simple) and most other modules with
> configuration variables could benefit from it.)

I can agree with that enough to not argue about it.


> # 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.
> 
> I can see abstracting out the options into Exporter::Options (or
> something), but I don't think the pairwise thing can do so.  

Pairwise thing?


> I do think that we should get rid of '!symbol' and especially
> '/regex/'; they seem like an unnecessary complication.

Yeah, chuck 'em.  It would be interesting to see how often that's
getting used.


> # 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).
> 
> Maybe it's just me, but I didn't find Exporter difficult to use.  At the
> basic levels most people use it at, it's just:
>   -Stuff the default exports into @EXPORT.
>   -Stuff anything else that's public into @EXPORT_OK.
>
> Tags aren't much more d

RE: Perl 6's Exporter

2001-12-22 Thread Brent Dax

Michael G Schwern:
# 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.
#
# 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?"

That may be a good idea.  I'll consider it.  Can anybody think of a
reason against it?

# 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.

Huh?

# Why not just a regular function or method?

I like the idea of just dealing with Exporter in one statement and then
forgetting it even exists.  To me, something like:

use Exporter;
our $Exp=new Exporter;
$Exp.default=qw(foo bar);
$Exp.ok=qw(baz quux);
$Exp.tags=(':B' => [qw(bar baz)]);

is little better than:

use Exporter;
our @ISA='Exporter';
our @EXPORT=qw(foo bar);
our @EXPORT_OK=qw(baz quux);
our %EXPORT_TAGS=(':B' => [qw(bar baz)]);

A little less typing, perhaps, but still too much for my tastes.

# > 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

I disagree.  The first one is something I thought of because of the p5p
'exporting considered harmful' thread (i.e. importing 'Dumper' to
something more sensible); the second one is something many modules
implement hacks to do.  (Carp and CGI both do it in some way;
Data::Dumper, Test::(More|Simple) and most other modules with
configuration variables could benefit from it.)

# 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.

I can see abstracting out the options into Exporter::Options (or
something), but I don't think the pairwise thing can do so.  I do think
that we should get rid of '!symbol' and especially '/regex/'; they seem
like an unnecessary complication.

# 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).

Maybe it's just me, but I didn't find Exporter difficult to use.  At the
basic levels most people use it at, it's just:
-Stuff the default exports into @EXPORT.
-Stuff anything else that's public into @EXPORT_OK.

Tags aren't much more difficult either.  @EXPORT_FAIL is just weird,
though--I don't know why it's there.

# 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 interesti

Re: Perl 6's Exporter

2001-12-22 Thread Michael G Schwern

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.

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/

Re: Perl 6's Exporter

2001-12-22 Thread Uri Guttman

> "BD" == Brent Dax <[EMAIL PROTECTED]> writes:

  BD> # >   1. Choosing where to export to:
  BD> # >   use Data::Dumper 'Dumper' => 'dumpvar';
  BD> # >   #exports Data::Dumper::Dumper to Main::dumpvar
  BD> # (or whatever)
  BD> #
  BD> # Where to import to.  It's probably not a good idea to export
  BD> # into someone
  BD> # else's namespace.  (Pull vs Push).

  BD> Ack, I hate terminology bugs.  Import to.  As for someone else's
  BD> namespace, under the current implementation (*bursts out
  BD> laughing*) that don't work too well anyway.

i already support that type of customized import in a trace/debug
module. in the use line i pass in an option key/value pair of sub =>
name and the sub is imported with that name. as the sub is a closure and
can be one of several calling styles (selected by another option), you
can import it multiple times (with multiple use statements) and get
different imported subs.

it looks like this:

use Debug sub => 'foo', style => 'text_args', level => 5 ;
use Debug sub => 'bar', style => 'key_value', level => 3 ;

foo 'send text only to debug system' ;

bar 'text' => 'send this text, override the level', level => 4 ;

this is all done by a single import sub in that module. in fact it is
the only sub in that module.

generalizing this to be used in Exporter would not be easy as it creates
closures (e.g. storing the debug level) and can even select the code ref
to use. you would have to pass too much info to Exporter to make this
work.

uri

-- 
Uri Guttman  --  [EMAIL PROTECTED]   http://www.stemsystems.com
-- Stem is an Open Source Network Development Toolkit and Application Suite -
- Stem and Perl Development, Systems Architecture, Design and Coding 
Search or Offer Perl Jobs    http://jobs.perl.org



Re: Perl 6's Exporter

2001-12-22 Thread Bryan C. Warnock

On Saturday 22 December 2001 05:40 am, Brent Dax wrote:

> BTW, can we genericize 'use' to work like an indirect-object method?
>
>   use Data::Dumper;
>   Data::Dumper.use;   #same thing

Only if you can gel the compile-time semantics of compile-and-run.

> # Well, I can't get it to run  :-)
>
> Darn, I was hoping you had brought a Perl 6 binary back from the
> future... :^)  Still, can you give it a once-over and tell me if you
> notice anything?

If I had done that, I'd be submitting a hell of a lot more code than I have 
been.  ;-)

A quick glance through with tired eyes looked good, but I'll do a more 
thorough paper trace when a little more coherent.  (At least I was able to 
mostly understand what you were doing.)

-- 
Bryan C. Warnock
[EMAIL PROTECTED]



RE: Perl 6's Exporter

2001-12-22 Thread Brent Dax

Bryan C. Warnock:
# On Saturday 22 December 2001 02:29 am, Brent Dax wrote:
# > I've been thinking about improvements that could be made to
# Exporter for
# > Perl 6.
# >
# > 1. Choosing where to export to:
# > use Data::Dumper 'Dumper' => 'dumpvar';
# > #exports Data::Dumper::Dumper to Main::dumpvar
# (or whatever)
#
# Where to import to.  It's probably not a good idea to export
# into someone
# else's namespace.  (Pull vs Push).

Ack, I hate terminology bugs.  Import to.  As for someone else's
namespace, under the current implementation (*bursts out laughing*) that
don't work too well anyway.

# > 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
#
# Is it more or less confusing (overall) to be mixing
# importation with simple,
# non-imported data initialization, as opposed to having it all
# be imported
# (with optional data initialization)?

There are already modules that do things like this.  For example:

use CGI '-debug';

I'm just building that capability into Exporter.  The other possibility
I can think of for it is like:

use Data::Dumper : '-Useqq';#on
no Data::Dumper  : '-Useqq';#off

Except that will try to do Data::Dumper::import('Data::Dumper' :
'-Useqq'), unless we special case use/no.  Ack.  Maybe we can just mix
switches and non-switches:

use Data::Dumper qw(Dumper -Useqq);

Should work, I suppose.

BTW, can we genericize 'use' to work like an indirect-object method?

use Data::Dumper;
Data::Dumper.use;   #same thing

# > 3. Warnings about conflicts:
# > use warnings 'Exporter';
# > sub Dumper { ... }
# > use Data::Dumper qw(Dumper);
# > #prints out a warning (not just 'redefined
# subroutine', either).
# > 4. For modules, saying 'use Exporter' should be enough
# to get import.
# >If you don't want Exporter's import(), just C.
# > 5. In addition to @EXPORT/@EXPORT_OK/%EXPORT_TAGS,
# provide a way to do
# >it on the 'use Exporter' line.
# >
# > So, with those requirements and what knowledge of Perl 6 I have, I
# > present a preliminary Exporter.  I typed it directly into
# the mailer, so
# > there's a good chance of mistakes.  If anyone spots any
# mistakes in it,
# > let me know.
#
# Well, I can't get it to run  :-)

Darn, I was hoping you had brought a Perl 6 binary back from the
future... :^)  Still, can you give it a once-over and tell me if you
notice anything?

--Brent Dax
[EMAIL PROTECTED]
Configure pumpking for Perl 6

"Nothing important happened today."
--George III of England's diary entry for 4-Jul-1776




Re: Perl 6's Exporter

2001-12-22 Thread Bryan C. Warnock

On Saturday 22 December 2001 02:29 am, Brent Dax wrote:
> I've been thinking about improvements that could be made to Exporter for
> Perl 6.
>
>   1. Choosing where to export to:
>   use Data::Dumper 'Dumper' => 'dumpvar';
>   #exports Data::Dumper::Dumper to Main::dumpvar (or whatever)

Where to import to.  It's probably not a good idea to export into someone 
else's namespace.  (Pull vs Push).

>   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

Is it more or less confusing (overall) to be mixing importation with simple, 
non-imported data initialization, as opposed to having it all be imported 
(with optional data initialization)?  

>   3. Warnings about conflicts:
>   use warnings 'Exporter';
>   sub Dumper { ... }
>   use Data::Dumper qw(Dumper);
>   #prints out a warning (not just 'redefined subroutine', either).
>   4. For modules, saying 'use Exporter' should be enough to get import.
>  If you don't want Exporter's import(), just C.
>   5. In addition to @EXPORT/@EXPORT_OK/%EXPORT_TAGS, provide a way to do
>  it on the 'use Exporter' line.
>
> So, with those requirements and what knowledge of Perl 6 I have, I
> present a preliminary Exporter.  I typed it directly into the mailer, so
> there's a good chance of mistakes.  If anyone spots any mistakes in it,
> let me know.

Well, I can't get it to run  :-)

-- 
Bryan C. Warnock
[EMAIL PROTECTED]



RE: Taking bakcups of a files in directory structure

2001-12-22 Thread Brent Dax

Richard J Cox:
# [EMAIL PROTECTED] (Brent Dax) wrote:
# > krish:
# > # I am a beginner in Perl and have a very trivial query. I have
# > # some .expect
# [...]
# >
# > This is the wrong group for this sort of question.
# perl6-internals is
#
# s/internals/language/

Doh!  got the groups mixed up...

# but the rest does apply (it's surprising there are not more such
# mis-targetted messages).

Not really.  People probably see that, say "but I'm using Perl 5!", and
go pester perl5-porters instead.  :^)

--Brent Dax
[EMAIL PROTECTED]
Configure pumpking for Perl 6

"Nothing important happened today."
--George III of England's diary entry for 4-Jul-1776




RE: Taking bakcups of a files in directory structure

2001-12-22 Thread Richard J Cox

In article <[EMAIL PROTECTED]>, 
[EMAIL PROTECTED] (Brent Dax) wrote:
> krish:
> # I am a beginner in Perl and have a very trivial query. I have
> # some .expect
[...]
> 
> This is the wrong group for this sort of question.  perl6-internals is

s/internals/language/


but the rest does apply (it's surprising there are not more such 
mis-targetted messages).

-- 
[EMAIL PROTECTED]