What do use and require evaluate to?

9 views
Skip to first unread message

Ingo Blechschmidt

unread,
Jul 12, 2005, 8:15:30 AM7/12/05
to perl6-l...@perl.org
Hi,

what do use and require evaluate to?

S06 suggests it's probably some kind of Module object:
The result of a use statement is a (compile-time) object that also has
an .assuming method, allowing the user to bind parameters in all the
module's subroutines/methods/etc. simultaneously:

     (use IO::Logging).assuming(logfile => ".log")

We could make (use Foo) evaluate to the class object Foo,
allowing:

my $foo = (use Foo).new(...);

Alternatively, we could go the Perl 5 way and return the
last thing evaluated in Foo.pm (which might be a Module
object, assuming that module Foo {...} evaluates to Foo).


What do successive uses of use and require evaluate to?
Perl 5 is inconsistent:

$ cat > Foo.pm
package Foo; 42;
$ perl -we 'warn require Foo; warn require Foo'
42 at -e line 1.
1 at -e line 1.

I'd like Perl 6's use and require to return the same thing.


In Perl 5, %INC maps the partial path names of the modules
loaded to their absolute ones. What should the keys and values
of %*INC be in Perl 6?


--Ingo

--
Linux, the choice of a GNU | self-reference, n. - See self-reference
generation on a dual AMD |
Athlon! |

Gaal Yahas

unread,
Jul 12, 2005, 1:48:41 PM7/12/05
to Ingo Blechschmidt, perl6-l...@perl.org
On Tue, Jul 12, 2005 at 12:15:30PM +0000, Ingo Blechschmidt wrote:
> In Perl 5, %INC maps the partial path names of the modules
> loaded to their absolute ones. What should the keys and values
> of %*INC be in Perl 6?

Conceptually, the Perl 5 %INC maps from what to which. It also imposes
a coupling with the filesystem which makes things like require $module
awkward. The hook mechanism in values breaks consistency, unless you
think of string values as shorthand for sub { slurp "path" }.

I propose to throw away the filesystem coupling, and map from a more
general name of the bit of code we are requiring to a more general
description of which instance of it we actually got. Once modules return
interesting values, it might be useful to keep a copy of that value
somewhere on the value side of %*INC: or else turn it inside out and
stipulate that a standard field in the Module object is where you got
this particular module. Probably, %*INC values should be weak references.

On the key side, I think we should allow more than just strings.
`use Bar` and `require Bar` invoke the module loader on a
ModuleName.new("Bar"). Passing a straight string performs this promotion
automatically. Path separators and '.pm' need never seen outside the
module loader. You can also ask to use/require a File or a URI, but
those requests are only honored if you have appropriate entries in the
module search path. In the case of URIs we could allow, for example,
only modules from a particular domain or even under a particular path.

Examples:

%*INC = (
# weak references
ModuleName.new("Bar") => Module.new(name => "Bar",
version => "0.0.7",
author => "BarCom",
path => "/usr/lib/perl6/Bar.pm",
loaded_classes =>
(::Bar, ::Bar::Internals),
),

URI.new("http://codeIZus.com/perl/randommodule.cgi") =>
Module.new(name => "Acme::emcA", ...),

$an_open_file => ...
);

@*INC = ("/usr/local/lib/perl6",
URI.new("http://codeIZus.com/perl/"),
URI.new("http://"), # this would mean allow loading code from ANYWHERE.
);

--
Gaal Yahas <ga...@forum2.org>
http://gaal.livejournal.com/

Larry Wall

unread,
Jul 12, 2005, 4:36:25 PM7/12/05
to perl6-l...@perl.org
On Tue, Jul 12, 2005 at 12:15:30PM +0000, Ingo Blechschmidt wrote:
: Hi,
:
: what do use and require evaluate to?
:
: S06 suggests it's probably some kind of Module object:
: The result of a use statement is a (compile-time) object that also has
: an .assuming method, allowing the user to bind parameters in all the
: module's subroutines/methods/etc. simultaneously:
:
:      (use IO::Logging).assuming(logfile => ".log")
:
: We could make (use Foo) evaluate to the class object Foo,
: allowing:
:
: my $foo = (use Foo).new(...);

I don't think it's wise to presume a magical binding between the package
name and the file name in this case.

: Alternatively, we could go the Perl 5 way and return the

: last thing evaluated in Foo.pm (which might be a Module
: object, assuming that module Foo {...} evaluates to Foo).

That works for me. I would note that when you say

module Foo;
...

it is equivalent to

module Foo {
...
}

so the first form does in fact return the module as the last (and only)
statement in the file. Presumbaly one can override this with an
explicit return.

: What do successive uses of use and require evaluate to?

: Perl 5 is inconsistent:
:
: $ cat > Foo.pm
: package Foo; 42;
: $ perl -we 'warn require Foo; warn require Foo'
: 42 at -e line 1.
: 1 at -e line 1.
:
: I'd like Perl 6's use and require to return the same thing.

They will. It'll be the "last thing", as defined above to usually
mean "the whole thing". In the case of separate compilation this
may actually be a proxy or stub for the module or class that is just
smart enough to manage the interface to the module/class without
necessarily knowing the implementation. (This does imply that
used modules must be compiled no later than "use" time, since we
can't know what the module exports without compiling it.)

: In Perl 5, %INC maps the partial path names of the modules

: loaded to their absolute ones. What should the keys and values
: of %*INC be in Perl 6?

It's not clear that Perl 6 will use the same search strategy for
modules, so there may not even be a %INC, or if there is, there's no
guarantee what the keys and values will really be. This has not yet
been specified. But searching a path of directories is certainly
one thing that slows down Perl 5 startup times. Whether or not the
Perl 6 library system is implemented using a database or flat files,
the search for a module matching various criteria will likely be in
some kind of index rather than doing probes on the bare filesystem.
There might well be a %INC, but its value might well be that very
package and/or proxy object we were discussing above, and what file
it came from might just be part of its metadata. Also, if the key
of %INC is the short name of a module, than it really has to be
kept per lexical scope, since different lexical scopes are allowed
to have different mappings from short names to long, so that we
can have dependencies on two different versions of the same module
simultaneously (to the extent allowed by shared resources).

In short, Perl 5 code that assumes too much knowledge about %INC
will have to be recoded to work under Perl 6.

Larry

Larry Wall

unread,
Jul 13, 2005, 8:02:38 PM7/13/05
to perl6-l...@perl.org
On Tue, Jul 12, 2005 at 08:48:41PM +0300, Gaal Yahas wrote:
: I propose to throw away the filesystem coupling, and map from a more

: general name of the bit of code we are requiring to a more general
: description of which instance of it we actually got. Once modules return
: interesting values, it might be useful to keep a copy of that value
: somewhere on the value side of %*INC: or else turn it inside out and
: stipulate that a standard field in the Module object is where you got
: this particular module.

Yes, that's basically what I was mumbling about in my response. Now just
make sure %*INC is lexically scoped.

: Probably, %*INC values should be weak references.

Why should they be weak references? If %*INC is lexically scoped
then its entries represent this lexical scope's *real* references to
modules, and there's no need to weaken them, since it's not functioning
as some kind of cache. As long as this lexical scope sticks around, it
needs the modules it points to. As soon as the lexical scope is destroyed,
it doesn't need them any more. (Counting all closures over this lexical
scope as preserving its needfulness, until all such closures are dead
objects.)

It's my conjecture that any explicit need for weak references probably
indicates a design failure somewhere. Something like the mis-scoping
of a reference variable, or maybe only something niggly like the
absence of a feature like "is cached" to encapsulate weak semantics.
Or maybe something as major as the lack of robust GC, in the case of
Perl 5...

Of course, *somebody* has to write the internals for "is cached".
But we already know that all optimizations are a form of cheating. :-)

Larry

Piers Cawley

unread,
Jul 14, 2005, 6:09:40 AM7/14/05
to perl6-l...@perl.org
Larry Wall <la...@wall.org> writes:

So long as there's some way of asking the garbage collector for everything in
the live set so you can grep through them I'm sure you're right. Because almost
everything is extensible at runtime a class is going to need some way of
finding all its (and its subclasses) instances so it can update 'em when/if
it's definition changes. I'm also trying to think how an object/database mapper
could be made to work effectively without being able to keep track of all its
managed objects, or would that just be handled through the use of 'is cached'?

Larry Wall

unread,
Jul 14, 2005, 2:32:58 PM7/14/05
to perl6-l...@perl.org
On Thu, Jul 14, 2005 at 11:09:40AM +0100, Piers Cawley wrote:
: So long as there's some way of asking the garbage collector for everything in

: the live set so you can grep through them I'm sure you're right. Because almost
: everything is extensible at runtime a class is going to need some way of
: finding all its (and its subclasses) instances so it can update 'em when/if
: it's definition changes. I'm also trying to think how an object/database mapper
: could be made to work effectively without being able to keep track of all its
: managed objects, or would that just be handled through the use of 'is cached'?

I just said it was my conjecture. That doesn't mean I think it's right. :-)

Larry

Reply all
Reply to author
Forward
0 new messages