develooper Front page | perl.module-authors | Postings from March 2022

Re: Exporter and subroutine circular dependencies between modules

Thread Previous | Thread Next
From:
David Christensen
Date:
March 14, 2022 01:44
Subject:
Re: Exporter and subroutine circular dependencies between modules
Message ID:
a263a4ba-019c-c4f1-3b62-4584eb767e3d@holgerdanske.com
On 3/13/22 15:08, Diab Jerius via module-authors wrote:
> On 3/13/22 16:13, David Christensen wrote:
>> module-authors:
>>
>> I have been wrestling with the Exporter module and subroutine circular 
>> dependencies between modules for a number of years.  I have yet to 
>> find a satisfactory solution.

> If you move import of modules with circular dependencies to runtime 
> rather than compile time:
> 
> 
>     $ diff Exporter-circular-use{.orig,.new}
>     diff Exporter-circular-use.orig/Bar11.pm
>     Exporter-circular-use.new/Bar11.pm
>     13c13,14
>     < use Foo11;
>     ---
>      > require Foo11;
>      > Foo11->import;
>     diff Exporter-circular-use.orig/Foo11.pm
>     Exporter-circular-use.new/Foo11.pm
>     13c13,14
>     < use Bar11;
>     ---
>      > require Bar11;
>      > Bar11->import;
> 
> 
>     $ perl Exporter-circular-use.t
>     ok 1 - foo00
>     ok 2 - foo01
>     ok 3 - foo10
>     ok 4 - foo11
>     1..4


Thank you for the reply.  :-)


Yes, that works.


>   Or move the export completely into compile time:
> 
>     $ diff Exporter-circular-use{.orig,.new}
>     diff Exporter-circular-use.orig/Bar11.pm
>     Exporter-circular-use.new/Bar11.pm
>     9,11c9,11
>     < require Exporter;
>     < our @ISA    = qw( Exporter );
>     < our @EXPORT    = qw( bar );
>     ---
>      > use parent 'Exporter';
>      > our @EXPORT;
>      > BEGIN{ @EXPORT = qw( bar ); }
>     diff Exporter-circular-use.orig/Foo11.pm
>     Exporter-circular-use.new/Foo11.pm
>     9,11c9,11
>     < require Exporter;
>     < our @ISA    = qw( Exporter );
>     < our @EXPORT    = qw( foo );
>     ---
>      > use parent 'Exporter';
>      > our @EXPORT;
>      > BEGIN { @EXPORT = qw( foo ); }


Yes, that also works.  Putting the @EXPORT allocation and initialization 
in a BEGIN block ahead of the 'use parent' looks even better:

2022-03-13 18:15:46 dpchrist@tinkywinky 
~/samba/dpchrist/sandbox/perl/Exporter-circular-use
$ diff Foo11.pm Foo33.pm
1c1
< package Foo11;
---
 > package Foo33;
9,11c9,10
< require Exporter;
< our @ISA	= qw( Exporter );
< our @EXPORT	= qw( foo );
---
 > BEGIN { our @EXPORT = qw( foo ) }
 > use parent 'Exporter';
13c12
< use Bar11;
---
 > use Bar33;


David



2022-03-13 18:38:24 dpchrist@tinkywinky 
~/samba/dpchrist/sandbox/perl/Exporter-circular-use
$ cat /etc/debian_version ; uname -a ; perl -v | head -n 2
9.13
Linux tinkywinky 4.9.0-17-amd64 #1 SMP Debian 4.9.290-1 (2021-12-12) 
x86_64 GNU/Linux

This is perl 5, version 24, subversion 1 (v5.24.1) built for 
x86_64-linux-gnu-thread-multi

2022-03-13 18:40:00 dpchrist@tinkywinky 
~/samba/dpchrist/sandbox/perl/Exporter-circular-use
$ ./Exporter-circular-use.t
ok 1 - foo00
ok 2 - foo01
ok 3 - foo10
Undefined subroutine &Bar11::foo called at Bar11.pm line 22.
not ok 4 - foo11
#   Failed test 'foo11'
#   at ./Exporter-circular-use.t line 24.
#          got: 'main=7
#  foo=6
#   bar=5
# '
#     expected: 'main=7
#  foo=6
#   bar=5
#    foo=4
#     bar=3
#      foo=2
#       bar=1
# '
Undefined subroutine &Bar12::foo called at Bar12.pm line 23.
not ok 5 - foo12
#   Failed test 'foo12'
#   at ./Exporter-circular-use.t line 24.
#          got: 'main=7
#  foo=6
#   bar=5
# '
#     expected: 'main=7
#  foo=6
#   bar=5
#    foo=4
#     bar=3
#      foo=2
#       bar=1
# '
ok 6 - foo21
ok 7 - foo22
ok 8 - foo33
1..8
# Looks like you failed 2 tests of 8.
Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About