Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

How do I initiate a constant with variable value?

by accessdenied (Acolyte)
on Jun 04, 2010 at 13:07 UTC ( [id://843110]=perlquestion: print w/replies, xml ) Need Help??

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

Hi.

I would like to create a constant but it's value is known only in runtume.

I did like this:

my $someVar = "someValue"; use constant CNST => $someVar;

but running this code

print('Got const [', CNST, ']');

I got warning "use of uninitialized ..." and brackets are empty - [].

Is there any way to initialize constant like I want?

What I'm trying to do is having some object which is defined in the module and which can be used from script which uses this module but in readonly mode.

I can define our $var which will be available with $MODULE::var but this allow to change value and I would like to avoid change.

Replies are listed 'Best First'.
Re: How do I initiate a constant with variable value?
by almut (Canon) on Jun 04, 2010 at 14:32 UTC

    Try Scalar::Readonly.  It's a tiny module, and variables made readonly with it are significantly faster than those of Readonly (because the latter uses the relatively slow tie mechanism).

    But note that readonlyness can just as easily be turned off again, because the module just toggles Perl's internal readonly flag.  In other words, it's not the right tool to keep intentional evildoers from messing with your variables...

Re: How do I initiate a constant with variable value?
by kennethk (Abbot) on Jun 04, 2010 at 13:43 UTC
    It seems like a simpler and more natural approach would be to define a getter in the module, a la

    my $someVar = "someValue"; sub get_cnst { return $someVar; }

    In this way, the variable is readable but not writable from outside the module. Is there a particular reason it needs to be a simple scalar?

      Tried so many times so I forgot to mention additional requirements, sorry.

      I don't like using getter because there are several scripts which uses module and several modules also, so number of getters and calls to them becomes big. Calls costs time and my task is optimisation so I would like to avoid getters.

      By the way, I found that constants in Perl actually implemented by subs, so each mention of constant is actually call to sub which returns value. As for me this looks like having getters. So, looks like I don't need constants really. I need some way to define readonly object without use of additional modules and other time-spending things.

        If you want it to be initialized once at run time and universally accessible for the remainder of the script's life, you could also accomplish this using a closure:

        #!/usr/bin/perl use strict; use warnings; sub definer { my $value = shift; sub outputter { no warnings "closure"; print "$value\n"; } } definer(5); outputter(); definer(6); outputter();

        If you are optimizing, do some profiling first to make sure that you are actually optimizing where it is needed - check out Devel::NYTProf. If you are worried about overhead introduced by function calls, it's possible Perl is not the best tool for this job or that you should delve into perlxs. But profile first and often.

        How does a module cost you time? I really doubt that you have profiled your script to determine that using modules is what costs you time.

Re: How do I initiate a constant with variable value?
by Anonymous Monk on Jun 04, 2010 at 13:43 UTC
    I would like to create a constant but it's value is known only in runtume.

    Then you want Readonly, not a constant.

      My task is optimisation so I would like to make code as simple as possible, without use of additional modules and other time-spending things.

      Thank you for info, I'll check if it fits my case.

Re: How do I initiate a constant with variable value?
by JavaFan (Canon) on Jun 04, 2010 at 15:51 UTC
    What I'm trying to do is having some object which is defined in the module and which can be used from script which uses this module but in readonly mode.
    Uhm, what's a "read-only object"? Note that objects are references, and even if you make the reference read-only, you can still access (and modify (unless that itself has been made read-only)) whatever it's pointing to. So, if you have a traditional, hashref based object, make the reference "constant" or "read-only" doesn't mean the objects state is suddenly unmutable.
Re: How do I initiate a constant with variable value?
by Jenda (Abbot) on Jun 06, 2010 at 19:42 UTC

    The $someVar = "someValue" assignment runs too late.

    Anyway there's nothing preventing you from using an expression in the "use constant" statement:

    use constant CNST => ($ENV{DEBUG} ? 1 : 0);

    You just have to keep in mind that the use statement is executed in "compile time" and therefore you can't use values computed at "run time". On the other time the "compile time" is just before the "run time", not days or months before as with C or something else that lets you compile your program and store the compiled version. Even in case you use PAR or PerlApp or Perl2Exe!

    Jenda
    Enoch was right!
    Enjoy the last years of Rome.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://843110]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (2)
As of 2024-04-19 19:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found