http://www.perlmonks.org?node_id=812972

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

Dear monks,

I've tried to print a constant which is declared in main package. But, it's printing error. I don't know where I made the mistake. The code is as follows.

pq.pm
package pq; use strict; use warnings; use constant { ONE => "1" }; sub new { my ($class) = @_; bless {}, $class; } sub pr { print main::FO1; } 1;
pl file
use strict; use warnings; use pq; use constant { FO1 => "value" }; print pq::ONE; # Prints 1, working right.! my $obj = new pq; pq->pr(); # says 'print() on unopened filehandle FO1 at pq.pm l +ine 28.'

Replies are listed 'Best First'.
Re: Accessing main::Constant
by BrowserUk (Patriarch) on Dec 16, 2009 at 05:32 UTC

    Use: sub pr { print main::FO1(); }


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Thanks. It works fine.

      I need another clarification, Is it possible to access a variable in main package like below,

      package pq; . use constant { VAR => "main::$VAR" }; . . sub pr { print main::$VAR; print VAR; }

      I'm getting error. So I thought, 'As the constants are expanded when compilation, it isn't working as what I expected'. $VAR is a our variable in main package.

        Firstly, the syntax would be $main::VAR

        Secondly, the value of variables in main are not set until after the uses at the top of the code, so you would get undef. You could address that by setting the $VAR in a BEGIN block:

        ... BEGIN{ our $VAR = 'fred'; } use pg; ...

        But the question is why would you want to do that?


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
        $main::VAR is the appropriate syntax.

        ( Woops, this was said in an earlier reply. I had missed it )

Re: Accessing main::Constant
by biohisham (Priest) on Dec 16, 2009 at 08:07 UTC
    First things first, accessing a class component in a fashion similar to "print pq::ONE" doesn't quite express OOP as it should, the idea of classes in OOP is to provide for encapsulation of data and methods into objects and that these objects interface the class data and methods they are instances of.

    In your code, "my $obj = new pq;" brings an object into existence but to no avail since you've not used it... You declared a constant in the main package, since you wanted to access that constant with a class package and since that class has an object, use the object instead to call/invoke the class method through which you wanted to access that constant in main,

    use strict; use warnings; use pq; use constant { FO1 => "value" }; my $obj = new pq; #accessing a class through an object... print $obj->ONE; $obj->pr;
    OOP is about hiding data and routines away from the rest of the program to simplify the code and enhnace privacy..


    Excellence is an Endeavor of Persistence. Chance Favors a Prepared Mind.
Re: Accessing main::Constant
by bart (Canon) on Dec 17, 2009 at 09:02 UTC

    The reason for your error is because the snippet

    sub pr { print main::FO1; }

    is compiled before the the snippet

    use constant { FO1 => "value" };

    (BTW braces for constant?? Weird.)

    so perl has to apply some heuristics while parsing the former code. An all uppercase bareword ("FO1") as a first parameter to print, makes perl assume it's a filehandle.

    So what you must do is one of the following:

    1. Mark up the print line so it's clear that you don't mean a filehandle. Unfortunately, this:

      sub pr { print +main::FO1; }
      still isn't enough.. (Why not? I really expected that this would work.)

      But even if it did work, that probably would still leave you with a prototype mismatch error

    2. compile the constant definition for before you use pq;

    BTW It's considered best practice to start package (and module) names with an uppercase letter.

    Seeing the trouble with the former attempt at a solution, the latter definitely looks like the best option.

Re: Accessing main::Constant
by ikegami (Patriarch) on Dec 17, 2009 at 16:02 UTC
    The problem is that main::FO1 looks like a file handle. Workarounds:
    print main::FO1(); print "".main::FO1; print STDOUT main::FO1;

    That said, it makes no sense for a module to rely on the calling script to have a certain function defined.