Perl - delayed evaluation of variables?

D

ditman

Hi,

I have a script where I define a string at the top of the file.
The string includes a variable which is not set until later in the
script. As a result the variable is evaluated as null and does not
appear in the string.
Is there a way to say to the Perl interpreter - do not evaluate the
string defined at the start, but wait until it is used?

Code sample:

my $LANG_LOCALE; # defined, but null value

my $ERROR_MSG_BUILDVER_INI_MISSING = "BuildVer.ini file for service
not found at $_TOP/services/imApp/$LANG_LOCALE";

function show_message(){
$LANG_LOCALE = "de-DE";
print "$ERROR_MSG_BUILDVER_INI_MISSING";
}
 
S

smallpond

Hi,

I have a script where I define a string at the top of the file.
The string includes a variable which is not set until later in the
script. As a result the variable is evaluated as null and does not
appear in the string.
Is there a way to say to the Perl interpreter - do not evaluate the
string defined at the start, but wait until it is used?

Code sample:

my $LANG_LOCALE; # defined, but null value

my $ERROR_MSG_BUILDVER_INI_MISSING = "BuildVer.ini file for service
not found at $_TOP/services/imApp/$LANG_LOCALE";

function show_message(){
$LANG_LOCALE = "de-DE";
print "$ERROR_MSG_BUILDVER_INI_MISSING";

}


To do your function, just remove the quotes
so the variable is evaluated inside the function:

function show_message(){
$LANG_LOCALE = "de-DE";
print $ERROR_MSG_BUILDVER_INI_MISSING;
}

To answer your more general question, there is
no such thing as "defining" a string. You were
making an assignment, which does the evaluation
of the expression. If you really want to evaluate
an expression later, look at the eval function.
--S
 
S

smallpond

To do your function, just remove the quotes
so the variable is evaluated inside the function:

function show_message(){
$LANG_LOCALE = "de-DE";
print $ERROR_MSG_BUILDVER_INI_MISSING;

}

To answer your more general question, there is
no such thing as "defining" a string. You were
making an assignment, which does the evaluation
of the expression. If you really want to evaluate
an expression later, look at the eval function.
--S


Sorry. Meant to move the expression inside the
function, of course, not just the variable.
 
B

Ben Morrow

Quoth ditman said:
I have a script where I define a string at the top of the file.
The string includes a variable which is not set until later in the
script. As a result the variable is evaluated as null and does not
appear in the string.
Is there a way to say to the Perl interpreter - do not evaluate the
string defined at the start, but wait until it is used?

Code sample:

my $LANG_LOCALE; # defined, but null value

my $ERROR_MSG_BUILDVER_INI_MISSING = "BuildVer.ini file for service
not found at $_TOP/services/imApp/$LANG_LOCALE";

function show_message(){
$LANG_LOCALE = "de-DE";
print "$ERROR_MSG_BUILDVER_INI_MISSING";
}

You can use Scalar::Defer for this. Note that all variables used
(whether lexical or global) will need to be declared first.

#!/usr/bin/perl

use strict;
use warnings;

use Scalar::Defer qw/lazy/;

my $LANG_LOCALE;
our $_TOP;

# This can be as complicated an expression as you like, including
# multiple statements.

my $MSG = lazy { "Not found at $_TOP/services/imApp/$LANG_LOCALE" };

$LANG_LOCALE = 'en_GB';
$_TOP = '/foo/bar';

print $MSG;

This will only evaluate the interpolation once, then cache the result;
if you want it re-evaluated every time, use 'defer' instead of 'lazy'.

Ben
 
G

Gunnar Hjalmarsson

ditman said:
I have a script where I define a string at the top of the file.
The string includes a variable which is not set until later in the
script. As a result the variable is evaluated as null and does not
appear in the string.
Is there a way to say to the Perl interpreter - do not evaluate the
string defined at the start, but wait until it is used?

Code sample:

my $LANG_LOCALE; # defined, but null value

my $ERROR_MSG_BUILDVER_INI_MISSING = "BuildVer.ini file for service
not found at $_TOP/services/imApp/$LANG_LOCALE";

function show_message(){
$LANG_LOCALE = "de-DE";
print "$ERROR_MSG_BUILDVER_INI_MISSING";
}

Why don't you simply pass the variables to the function?

sub show_message {
my ($top, $lang) = @_;
print 'BuildVer.ini file for service not' .
" found at $top/services/imApp/$lang";
}

show_message( $_TOP, $LANG_LOCALE );
 
T

technut666

Sorry. Meant to move the expression inside the
function, of course, not just the variable.

Hi,

Thanks for you response! :D
The code sample was to just illustrate the issue - there is more going
on here.
Basically I have to declare a bunch of error messages at the start of
the script.
I then read in a file with a bunch of environment settings - one of
which is $lang_locale. So I can't know $lang_locale until after I
have declared the error messages. (Again a simplified description of
what is going on in the script :D )
 
T

technut666

Sure. Define the string when it is used.







Is there a reason you are not defining $LANG_LOCALE until show_message?
How are you attempting to find BuildVer.ini when you don't know where
$LANG_LOCALE is until you call the function that tells you you can't
find BuildVer.ini in a directory defined by $LANG_LOCALE?

--
Christopher Mattern

NOTICE
Thank you for noticing this new notice
Your noticing it has been noted
And will be reported to the authorities

Hi,

Thanks to everyone for your responses.
I am defining a bunch of error messages at the start of the script.
Then I read in a bunch of environment settings from an external file,
one of which is $LANG_LOCALE. So I can't know $LANG_LOCALE before I
declare the error message.

Fortunately I have found a solution in the Perl Cookbook of all
places! :D
It's not a delayed expansion, but it does what I need.

Goes something like this:
my $LANG_LOCALE; # defined, but null value

my $ERROR_MSG_BUILDVER_INI_MISSING = "BuildVer.ini file for service
not found at $_TOP/services/imApp/\$LANG_LOCALE";

function show_message(){
$LANG_LOCALE = "de-DE";
$ERROR_MSG_BUILDVER_INI_MISSING =~ s/(\$\w+)/$1/eeg;
print "$ERROR_MSG_BUILDVER_INI_MISSING";
}

Description:
Using the backslash before $LANG_LOCALE in the
$ERROR_MSG_BUILDVER_INI_MISSING string means it is not evaluated.
Then in the function, the regexp looks for anything which looks like a
variable (a dollar sign plus text).
This is captured as $1.
The 'ee' means "Evaluate the right side as a string then eval the
result". So if $1 is the string $LANG_LOCALE and $LANG_LOCALE="de-
DE", this is evaluated as "de-DE".
And the 'g' means operate globally obviously - so this will work for
all variables.
Hope this is clearly explained.

Regards,
C.
 
S

Skye Shaw!@#$

Hi,

I have a script where I define a string at the top of the file.
The string includes a variable which is not set until later in the
script.  As a result the variable is evaluated as null and does not
appear in the string.
Is there a way to say to the Perl interpreter - do not evaluate the
string defined at the start, but wait until it is used?
Yikes

Code sample:

my $LANG_LOCALE; # defined, but null value

my $ERROR_MSG_BUILDVER_INI_MISSING = "BuildVer.ini file for service
not found at $_TOP/services/imApp/$LANG_LOCALE";

function show_message(){
  $LANG_LOCALE = "de-DE";
  print "$ERROR_MSG_BUILDVER_INI_MISSING";

}

If you must:

my $LANG_LOCALE; # defined, but null value

my $ERROR_MSG_BUILDVER_INI_MISSING = 'print "BuildVer.ini file for
service
not found at $_TOP/services/imApp/$LANG_LOCALE"';

sub show_message {
$LANG_LOCALE = "de-DE";
eval $ERROR_MSG_BUILDVER_INI_MISSING";
}


If you really want to go the template route my not use printf?

my $ERROR_XYZ = 'Damn it Jim, I'm a %s not a %s';


printf $ERROR_XYZ, 'Aussie', 'Kiwi';

-Skye
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,575
Members
45,053
Latest member
billing-software

Latest Threads

Top