Re: Enabling all MY methods of the same name in multiple modules

[email protected] (David Christensen) Fri, 16 Jul 2021 15:23:31 -0700
Newsgroups perl.module-authors
Message-ID <[email protected]>
On 7/16/21 7:11 AM, Leon Timmermans wrote:
> On Fri, Jul 16, 2021 at 8:57 AM David Christensen <[email protected]>
> wrote:
> 
>> module-authors:
>>
>> I have extended EUMM in a Perl distribution by implementing a module
>> that overrides various methods in the "MY" package namespace and by
>> using that MY override module in Makefile.PL, per "Overriding MakeMaker
>> Methods" in:
>>
>>       https://metacpan.org/pod/ExtUtils::MakeMaker
>>
>>
>> I would like to split the single distribution into multiple
>> distributions.  Multiple distributions will have a MY override module.
>> A given MY method may be implemented in multiple modules.  A given
>> Makefile.PL may 'use' one or more modules.  Method name collisions are
>> expected.  I will architect the distributions to avoid circular
>> dependencies.
>>
>>
>> AIUI simply use'ing modules with the same package namespace and the same
>> subroutine (method) names will result in later definitions redefining
>> earlier definitions, generating compiler warnings and making the earlier
>> definitions inaccessible.
>>
>>
>> Is there a mechanism to daisy-chain multiple package::subroutine
>> definitions such that a MY method call by EUMM will return the
>> concatenated results of all definitions?
>>
>>
>> David
>>
> 
> In general, I don't think it's a good idea for any module to add methods to
> MY:: directly (or at least not by default), exactly for that reason.


Thank you for confirming the redefinition problem.


> MY should only live in Makefile.PL. 


As I will need this functionality in several Makefile.PL's, I plan to 
put the common code into a helper module.


> For methods without side-effects on $self,
> combining them is could be done like this:
> 
>   my @extensions = (...);
>   load($_) for @extensions;
>   my @methods = map { $_. "::postamble" } @extensions;
>   sub MY::postamble {
>     my ($self, %args) = @_;
>     return join "\n\n", map { $self->$_(%args) } @methods;
>   }


That looks like the right idea.  But, I may need code within 'package 
MY' for SUPER to work right.


> Another alternative is to insert yourself in the inheritance tree between
> MY:: and whatever happens to be its base-class ($MY::ISA[0]), so you can
> chain them. This may work better with side-effects.


That is a novel idea (for myself).  I will keep it in mind if other 
approaches fail.


Thank you for the reply.  :-)


David