dragonchild has asked for the wisdom of the Perl Monks concerning the following question:

Even though I solved my problem another way, I'm still curious. How would I know which phase (BEGIN, CHECK, INIT, END) I am in? Let's say, for the sake of a stupid example, I have some code that needs to use @a when in INIT and @b when in standard RUNTIME (or, lack of a phase). How would I do it?

Being right, does not endow the right to be rude; politeness costs nothing.
Being unknowing, is not the same as being stupid.
Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

Replies are listed 'Best First'.
Re: Which phase am I in?
by Velaki (Chaplain) on Nov 19, 2004 at 13:54 UTC

    What about setting a ref variable to point at the appropriate list in BEGIN, and then change it to point at the other list in INIT? Then, write all your code to use the ref variable.

    Just a thought,
    -v
    "Perl. There is no substitute."

      Or do something along the lines of this near the beginning of your code:

      BEGIN { $__KLUDGE::phase = 'BEGIN'; } INIT { $__KLUDGE::phase = 'INIT'; } CHECK { $__KLUDGE::phase = 'CHECK'; } END { $__KLUDGE::phase = 'END'; }

      And then check $__KLUDGE::phase as necessary.

        The END (and the CHECK?) would have to be at the end of the code, not the beginning. Maybe they should be in an eval "" at the end of your script, because they're done Last Encountered, First Executed order.
Re: Which phase am I in?
by tilly (Archbishop) on Nov 19, 2004 at 21:16 UTC
    I consider these phases arbitrary, and code which relies on them is fragile.

    Suppose that you have a module that I require from the body of my code. Then your BEGIN happens at the main run time of the program, and you never see CHECK or INIT. If you depended on initializations happening in CHECK or INIT, then they didn't. (Guess why I avoid attributes?) In fact if the require is triggered by a function call in an END block, then your BEGIN may be nested in an END. Going the other way if there is a compilation error, then even normal END blocks might be triggered while you are in compile phase.

    If you're doing mod_perl development with Apache::Reload, then this matters a lot because you will be reloading stuff at runtime. Being able to work with this module can speed up your development cycle a lot.

    So is BEGIN earlier or later than CHECK or INIT or END? It varies. Which ones are guaranteed to happen in your program? Assuming no errors, only BEGIN and END.

    Therefore I consider CHECK and INIT, or anything that depends on stuff happening during CHECK and INIT, to be fragile and to be avoided. (Then again I'm an old curmudgeon...)

      So, Oh Wise Curmudgeon, how would you write code that needs to do things after all compilation is done, but before execution starts?

      Real-life situation - I'm working on a class lazyloader (RFC: Object::Proxy (or somesuch) - ignore the Proxy part). The implementation I have chosen is to insert my own constructor in place of the constructor provided by the original author and rename the original one. However, my lazyloader will probably be used at the beginning and the constructor defined a bit later. I cannot rename what isn't there. In addition, I have to do my magic before anything calls the original constructor. What should i do?

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        I wouldn't try to write that code.

        Or if I did, I'd do as some of the modules that you rejected did and not try to retrofit semantics onto the existing module. Instead I'd provide the lazy version of the constructor under a different name.

        And an extension of what I said above is that I won't choose to use modules - including the one that you're writing - that depend on working that way. Because how they are trying to be clever conflicts with how I'd prefer to be clever, so they will be fragile for me.

        That's the problem with any code that fmucks with the Symbol table!

        Of course, if you call it "mucking with the symbol table", then you can look down your nose at it, with assurdness that "you shoudln't be doing that".

        If you called "Introspection", or "dynamic programming", then (at least in some languages), you could laud it it as a "useful, valueable, even desirable feature of the language".


        Examine what is said, not who speaks.
        "But you should never overestimate the ingenuity of the sceptics to come up with a counter-argument." -Myles Allen
        "Think for yourself!" - Abigail        "Time is a poor substitute for thought"--theorbtwo         "Efficiency is intelligent laziness." -David Dunham
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
        Class::Autouse won't cut it for you as a class lazy-loader?
Re: Which phase am I in?
by kappa (Chaplain) on Nov 19, 2004 at 16:24 UTC
    Those "phases" are just fancy magical subs which permit declaration without the sub keyword. You can happily use caller EXPR to examine the callstack and find out the exact place you were called from.
      #!/usr/local/perl5/bin/perl my @x; sub call { push @x, [caller(1)] } BEGIN { call() } CHECK { call() } INIT { call() } END { print "@$_\n" for @x; } END { call() }

      will sometimes give me BEGIN and INIT, sometimes BEGIN, CHECK, and END. But, never all four. What am I doing wrong? I'm on 5.8.4 for Solaris8.

      Update: Of course, I'm not seeing it cause gvim isn't a true IDE. Running from the commandline fixes the problem.

      Being right, does not endow the right to be rude; politeness costs nothing.
      Being unknowing, is not the same as being stupid.
      Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
      Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

        ActiveState 5.8.4-810 gives me all four.

        main f.txt 3 main::BEGIN 1 0 0 main f.txt 0 main::CHECK 1 0 0 main f.txt 0 main::INIT 1 0 0 main f.txt 0 main::END 1 0 0
Re: Which phase am I in?
by Yendor (Pilgrim) on Nov 19, 2004 at 13:48 UTC

    Well, the standard way to do this has always been to take out your sextant, wait until night falls, pray to $DEITY that it's a clear night, and gaze at the stars. Start by finding Polaris, perform some complex calculations, and especially important at this point is to check the phase of the moon. Because your phase can never align exactly with the moon's phase. That would be bad, mmmkay?

    ;-)