File load vs. name load with require - perl bug? 
Author Message
 File load vs. name load with require - perl bug?

I hesitate to call this a perl bug, but the behavior we're seeing is
strongly counter-intuitive (and certainly not what we consider to
be correct).  We've boiled it down to a very small example, which is
included below.  When you run the example with various perls 5.003 thru
5.6.0, you get:

$ ./reqprob.pl
Blah blah blah in Obj.pm
Undefined subroutine &Obj2::run called at Obj2.pm line 6.
$

The code is as follows:

    ::::::::::::::
    Obj.pm
    ::::::::::::::
    package Obj;
    require './library.pl';

    sub doit
      {
        run( 'Blah blah blah in Obj.pm');
      }
    ::::::::::::::
    Obj2.pm
    ::::::::::::::
    package Obj2;
    require './library.pl';

    sub doit
      {
        run( 'Blah blah blah in Obj2.pm');
      }
    ::::::::::::::
    library.pl
    ::::::::::::::
    sub run
      {

        print $string."\n";
      }
    1;
    ::::::::::::::
    reqprob.pl
    ::::::::::::::
    #!/usr/local/bin/perl -w
    use Obj;
    use Obj2;

    doit Obj;
    doit Obj2;

On close reading of the camel book, cookbook, etc, we believe that what
is happening is:

  1. The require statement in Obj.pm is found, causing library.pl to be
     loaded by Obj.pm, with the name `run' defined within the Obj2 namespace.
     Perl notes that the file has been read.

  2. The require statement in Obj2.pm is found.  library.pl is seen to
     already have been read, and is therefore not-reread (correct behaviour,
     IMHO).

  3. Obj->doit() is invoked, which in turn invokes run().

  4. Obj2->doit() is invoked, which attempts to invoke run() but fails
     because it cannot find the name in its namespace.

If the above examples are rewritten so all occurences of `run' are
replaced with `main::run', it works correctly.  If you make library.pl
a true module (with EXPORT defined) and 'use' rather than 'require'
it, it works correctly  There are also other workarounds but before you
start trotting them out remember -- the above is a very simple example
designed to show the problem.  We found it in a much more signficant
piece of code, and workarounds will be significantly harder to apply.
So let's focus on the above example, and the issue we want to question:

We believe that when it is detected that library.pl is already loaded
while handling Obj2.pm (step 2, above), perl errs in not making the
functions declared in library.pl available in Obj2 as well.  Is this
what is intended that perl do?  Or have we found a bug?
--
Better to be good without reason than to be evil for a hundred good reasons.
  -- Gene Wolfe



Sun, 31 Aug 2003 05:55:07 GMT  
 File load vs. name load with require - perl bug?
: I hesitate to call this a perl bug
good

Output =>
: $ ./reqprob.pl
: Blah blah blah in Obj.pm
: Undefined subroutine &Obj2::run called at Obj2.pm line 6.
: $

Code =>
:     ::::::::::::::
:     Obj.pm
:     ::::::::::::::
:     package Obj;
:     require './library.pl';

:     sub doit
:       {
:       run( 'Blah blah blah in Obj.pm');
:       }
:     ::::::::::::::
:     Obj2.pm
:     ::::::::::::::
:     package Obj2;
:     require './library.pl';

:     sub doit
:       {
:       run( 'Blah blah blah in Obj2.pm');
:       }
:     ::::::::::::::
:     library.pl
:     ::::::::::::::
:     sub run
:       {

:       print $string."\n";
:       }
:     1;
:     ::::::::::::::
:     reqprob.pl
:     ::::::::::::::
:     #!/usr/local/bin/perl -w
:     use Obj;
:     use Obj2;

:     doit Obj;
:     doit Obj2;

: On close reading of the camel book, cookbook, etc, we believe that what

I'm afraid you should have done that "close reading" before you wrote the
code.

There are three choices

"use" - which does exactly what you want - that's why it exists.

"require" - which does exactly what some of us want some of the time, but
not what you wanted this time.

"do" - which would also work here, though is probably not the best choice
because the same code gets compiled each time and (because of the
different packages) each copy will take up its own memory to boot.

If you want a run time "use" then write => eval "use file";


or stick with require but add an import function that you explicitly call
each time the module is required.

By the way, I'm sure you have realized after that close reading that
because libary.pl does not declare a package it is getting compiled in the
package of the caller.

So, if Obj.pm is use'd first, then you end up with a function called
Obj::run.

On the other hand if Obj2.pm was use'd first then the function would be
compiled as Obj2::run.

In general, neither Perl nor your program would know which subroutines
where to be imported, even if Perl did what you think you want it to do.

My conclusion - it's not a perl bug - just the usual kind (that we all
make) - programmer misunderstanding.



Sun, 31 Aug 2003 14:21:47 GMT  
 File load vs. name load with require - perl bug?

Quote:

>   1. The require statement in Obj.pm is found, causing library.pl to be
>      loaded by Obj.pm, with the name `run' defined within the Obj2 namespace.
>      Perl notes that the file has been read.

Uhm, into the Obj namespace, but yes.

So, you've got Obj::doit, Obj::run, and library.pl is now loaded.

Quote:
>   2. The require statement in Obj2.pm is found.  library.pl is seen to
>      already have been read, and is therefore not-reread (correct behaviour,
>      IMHO).

Yes, so you've now got Obj::doit, Obj::run, Obj2::doit, and library.pl is
loaded. And we agree this is correct so far. :)

Quote:
>   3. Obj->doit() is invoked, which in turn invokes run().

Right.

Quote:
>   4. Obj2->doit() is invoked, which attempts to invoke run() but fails
>      because it cannot find the name in its namespace.

Sure; that makes perfect sense, given the above.

Quote:
> We believe that when it is detected that library.pl is already loaded
> while handling Obj2.pm (step 2, above), perl errs in not making the
> functions declared in library.pl available in Obj2 as well.

Why should it? You told perl to load in library.pl if it hadn't already
done it; it had already done so, so it didn't look at library.pl again.

If you want "do", use "do".

--
The UNIX system is harder to use than a toaster.  -Kaare Christian



Tue, 02 Sep 2003 00:05:43 GMT  
 
 [ 3 post ] 

 Relevant Pages 

1. compress mdb file

2. SRC: Devel::Loaded.pm - post-execution dump of loaded modules

3. Module loading error: Apache can't load Apache::Server

4. static load of dyn-load modules

5. Can't load module Tk, dynamic loading not available in this p

6. Cascading dynamic loading through requires

7. PERLFUNC: require - load in external functions from a library at runtime

8. PERLFUNC: require - load in external functions from a library at runtime

9. Readkey no longer works in Windows

10. DESENDING SORT OF DATES IN A TABLE

11. XS DLL name clashes with DLL that needs to load (Win32)

12. How to load the module with calculated name?

 

 
Powered by phpBB® Forum Software