in reply to Undefined subroutine errors

Design issues asside, Exporter needs to be loaded (and its configuration variables must be initialized) before the other module of the pair is loaded. Using the following templates will allow both modules to import from each other:

use strict; use warnings; package SpiderMan; BEGIN { our @ISA = qw( Exporter ... ); our @EXPORT_OK = qw( ... ); require Exporter; } use ...; use ...; use Doctor::Octopus; use ...; use ...; ... 1;
use strict; use warnings; package Doctor::Octopus; BEGIN { our @ISA = qw( Exporter ... ); our @EXPORT_OK = qw( ... ); require Exporter; } use ...; use ...; use SpiderMan; use ...; use ...; ... 1;

Replies are listed 'Best First'.
Re^2: Undefined subroutine errors
by Anonymous Monk on Oct 26, 2005 at 19:50 UTC
    You were correct. It works now. Thanks. Can you or someone else please tell me why I need the BEGIN blocks?

      use and BEGIN are executed as soon as they are compiled. Without the BEGIN, the following would happen:

      • Spiderman's use strict; is compiled.
      • Spiderman's use strict; is executed.
      • Spiderman's use warnings; is compiled.
      • Spiderman's use warnings; is executed.
      • What was in Spiderman's BEGIN is compiled.
      • Spiderman's use Doctor::Octopus; is compiled.
      • Spiderman's use Doctor::Octopus; is executed.
      • require Doctor::Octopus is executed.
        • Octopus's use strict; is compiled.
        • Octopus's use strict; is executed.
        • Octopus's use warnings; is compiled.
        • Octopus's use warnings; is executed.
        • What was in Octopus's BEGIN is compiled.
        • Octopus's use Spiderman; is compiled.
        • Octopus's use Spiderman; is executed.
        • Spiderman is already loaded, so it's not loaded again.
        • Spiderman is already loaded, so it's not executed again.
        • Spiderman->import doesn't exist, so it isn't called.
          This is the problem. Exporter hasn't been loaded yet, and the variables telling Exporter what Spiderman should export haven't been initialized.
        • The rest of Octopus is compiled.
        • What was in Octopus's BEGIN is executed.
        • The rest of Octopus is executed.
      • The rest of Spiderman is compiled.
      • What was in Spiderman's BEGIN is executed.
      • The rest of Spiderman is executed.
      • Doctor::Octopus->import is called.

      Remember that

      use Module

      means

      BEGIN { require Module; Module->import if Module->can('import'); }