Perl - delayed evaluation of variables?

Perl - delayed evaluation of variables?

am 17.04.2008 12:56:27 von 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";
}

Re: Perl - delayed evaluation of variables?

am 17.04.2008 14:00:15 von smallpond

On Apr 17, 6:56 am, ditman wrote:
> 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

Re: Perl - delayed evaluation of variables?

am 17.04.2008 14:04:26 von smallpond

On Apr 17, 8:00 am, smallpond wrote:
> On Apr 17, 6:56 am, ditman wrote:
>
>
>
> > 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


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

Re: Perl - delayed evaluation of variables?

am 17.04.2008 14:26:37 von Ben Morrow

Quoth ditman :
>
> 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

Re: Perl - delayed evaluation of variables?

am 17.04.2008 16:45:35 von Gunnar Hjalmarsson

ditman wrote:
> 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 );

--
Gunnar Hjalmarsson
Email: http://www.gunnar.cc/cgi-bin/contact.pl

Re: Perl - delayed evaluation of variables?

am 17.04.2008 16:46:22 von Chris Mattern

On 2008-04-17, ditman wrote:
> 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?

Sure. Define the string when 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";
> }

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

Re: Perl - delayed evaluation of variables?

am 17.04.2008 17:23:36 von ditman

On Apr 17, 1:04 pm, smallpond wrote:
> On Apr 17, 8:00 am, smallpond wrote:
>
>
>
> > On Apr 17, 6:56 am, ditman wrote:
>
> > > 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
>
> 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 )

Re: Perl - delayed evaluation of variables?

am 17.04.2008 17:40:52 von ditman

On Apr 17, 3:46 pm, Chris Mattern wrote:
> On 2008-04-17, ditman wrote:
>
> > 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?
>
> Sure. Define the string when 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";
> > }
>
> 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.

Re: Perl - delayed evaluation of variables?

am 18.04.2008 09:38:25 von skye.shaw

On Apr 17, 3:56=A0am, ditman wrote:
> 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. =A0As 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 =3D "BuildVer.ini file for service
> not found at $_TOP/services/imApp/$LANG_LOCALE";
>
> function show_message(){
> =A0 $LANG_LOCALE =3D "de-DE";
> =A0 print "$ERROR_MSG_BUILDVER_INI_MISSING";
>
> }

If you must:

my $LANG_LOCALE; # defined, but null value

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

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


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

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


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

-Skye