in reply to Re^3: Automatic vivification of an object
in thread Automatic vivification of an object

Quite possibly.

The basic class hierarchy I'm working with makes good design sense and is essentially a tree of classes with one base class that is subclassed one or more times, each of those is subclassed zero or more times, plus another layer or two of subclasses beyond that on some branches. Currently there is no multiple inheritance (though I don't think I can completely rule that out for the future). I also can't rule out the possibility that the base class won't someday be a subclass of another class (such as a standard Perl class of some kind).

Each class in the hierarchy has a hash variable that contains a set of values that add to and/or overload the same set of values from the parent class. I'd like to have a function in the parent class that creates a merged hash and caches that value (on the first call) or returns the cached value (on subsequent calls). I'd rather not copy a lot of code to each class to do the merging and caching in each class.

I have the above working just fine when called at runtime, but if I try to create an instance of the base class as part of module compilation (i.e., my $obj = classname->new(...) code outside of any sub declaration, not using a BEGIN block), it doesn't work. (I suspect it has something to do with the order in which variables are declared and/or initialized.) Hence, I am changing it to create the required object the first time it needs it rather than at compile time.

As this is a one-time step, any costs involved in eval (which I've now removed because it wasn't needed) or autoload is negligible in this case. Even so, I'm trying to minimize the impact so that I can use this as a generalized auto-vivification and/or delayed initialization solution in the future.

Replies are listed 'Best First'.
Re^5: Automatic vivification of an object
by Anonymous Monk on Jan 15, 2015 at 16:45 UTC
    ... but if I try to create an instance of the base class as part of module compilation ...

    Considering that seems to cause the problem, I'm curious as to why; what do you need that instance for?

    ... it doesn't work. (I suspect it has something to do with the order in which variables are declared and/or initialized.)

    Tracking down the source of that problem may prove insightful!

    The best thing to get people to take a look at it would be if you would provide a short, self-contained piece of example code that reproduces the problem (see http://sscce.org/).

      After thinking about it some more, I believe the issue can be simplified to these three files (all in one directory):

      AAA.pm
      #!/usr/bin/perl use strict; use warnings; package AAA; our $var = 'aaa'; warn $AAA::var; warn $BBB::var; 1;
      BBB.pm
      #!/usr/bin/perl use strict; use warnings; package BBB; use base 'AAA'; our $var = 'bbb'; warn $AAA::var; warn $BBB::var; 1;
      CCC.pl
      #!/usr/bin/perl use strict; use warnings; use BBB; warn $AAA::var; warn $BBB::var;

      I have strict and warnings in each file to ensure that all possible messages get printed out. Here's the output:

      aaa at AAA.pm line 10. Use of uninitialized value $BBB::var in warn at AAA.pm line 11. Warning: something's wrong at AAA.pm line 11. aaa at BBB.pm line 12. bbb at BBB.pm line 13. aaa at CCC.pl line 8. bbb at CCC.pl line 9.

      The issue is that the code needs to have access to the value of $BBB::var from AAA (in real code this would be by reference, eval, or some other method), but that value doesn't exist until after AAA is done being compiled. Therefore, if the code that needs that access can be deferred until after compliation is complete, then the value is available for use and all would work well.