help: having trouble evaluating expressions with EVAL

M

Mad Scientist Jr

I seem to be getting a syntax error when evaluating expressions with
Eval.

(Also, can someone show what the right way to trap the error is?)

Much appreciated...

#THIS WORKED:
if (1==2) {$answer1='answer1 evaluates to true';} else
{$answer1='answer1 evaluates to false';}
if (2==2) {$answer2='answer2 evaluates to true';} else
{$answer2='answer2 evaluates to false';}
print $answer1;
print $answer2;

#WHEN WE PUT THE ABOVE INSIDE 'EVAL' WE GET A SYNTAX ERROR:
$str = "if (1==2) {$answer1='answer1 evaluates to true';} else
{$answer1='answer1 evaluates to false';}";
eval $str;
$str = "if (2==2) {$answer2='answer2 evaluates to true';} else
{$answer2='answer2 evaluates to false';}";
eval $str;
print $answer1;
print $answer2;

#AFTER WE GET THE SIMPLE ONE WORKING WE'LL TRY THIS
#WE PROBABLY HAVE TO CONVERT THE OPERATORS TO PERL IE == NE GT ETC.
#$str = "if ( (17 >= 21) or (6.6 > 6.5) ) and (\"Bob\" <> \"leon\") and
(FALSE = false)";
 
I

Ignoramus20015

I seem to be getting a syntax error when evaluating expressions with
Eval.

(Also, can someone show what the right way to trap the error is?)

Much appreciated...

#THIS WORKED:
if (1==2) {$answer1='answer1 evaluates to true';} else
{$answer1='answer1 evaluates to false';}
if (2==2) {$answer2='answer2 evaluates to true';} else
{$answer2='answer2 evaluates to false';}
print $answer1;
print $answer2;

#WHEN WE PUT THE ABOVE INSIDE 'EVAL' WE GET A SYNTAX ERROR:
$str = "if (1==2) {$answer1='answer1 evaluates to true';} else
{$answer1='answer1 evaluates to false';}";
eval $str;

Assume that $answer1 is initially 'xyz' before you del;ve into your
script.

After the first assignment $str will be

"if (1==2) {xyz='answer1 evaluates to true';} else {xyz='answer1 evaluates to false';}";

that obviously will not evaluate to what you want.

Use \ in front of $answer.

i
 
M

Mad Scientist Jr

I see... thanks. I got it working.

However I have another question. Comparing booleans, why would "TRUE eq
true" evaluate to false?

Also, how would I compare a string with caps insensitive? eg, "bob" !=
"Bob"

Also, how would you compare 2 dates?

thanks again

#!/usr/local/bin/perl -- -*-perl-*-
#$exp = "(false eq false)"; RETURNS TRUE
$exp = "(FALSE eq false)"; RETURNS FALSE
#$exp = "(true eq true)"; RETURNS TRUE
#$exp = "(TRUE eq true)"; RETURNS FALSE
$str = "if ($exp) {\$answer=' evaluates to true';} else {\$answer='
evaluates to false';}";
eval $str or $answer = "answer evaluates to $@";
print $exp.$answer;
 
P

Paul Lalli

Mad said:
I seem to be getting a syntax error when evaluating expressions with
Eval.

(Also, can someone show what the right way to trap the error is?)

Much appreciated...

#THIS WORKED:
if (1==2) {$answer1='answer1 evaluates to true';} else
{$answer1='answer1 evaluates to false';}
if (2==2) {$answer2='answer2 evaluates to true';} else
{$answer2='answer2 evaluates to false';}
print $answer1;
print $answer2;

#WHEN WE PUT THE ABOVE INSIDE 'EVAL' WE GET A SYNTAX ERROR:
$str = "if (1==2) {$answer1='answer1 evaluates to true';} else
{$answer1='answer1 evaluates to false';}";
eval $str;
$str = "if (2==2) {$answer2='answer2 evaluates to true';} else
{$answer2='answer2 evaluates to false';}";
eval $str;
print $answer1;
print $answer2;

I don't get any syntax errors at all from copy and pasting that code.
I do, of course, get the standard errors and warnings if I enable
strict and warnings. Do you have strict and warnings enabled, like you
should?

What, exactly, is the text of the syntax errors you're getting?

As for what you're doing wrong, why don't you try printing out the
variable $str before you evaluate it, and see what you're actually
trying to evaluate.

I don't understand what you mean by "right way to trap the error".
eval() already traps errors - that's one of its main points. Syntax
and run-time errors that occurr within the string evaluated by eval()
will be stored in the $@ variable. You then check that variable to see
if there were any errors.
#AFTER WE GET THE SIMPLE ONE WORKING WE'LL TRY THIS
#WE PROBABLY HAVE TO CONVERT THE OPERATORS TO PERL IE == NE GT ETC.
#$str = "if ( (17 >= 21) or (6.6 > 6.5) ) and (\"Bob\" <> \"leon\") and
(FALSE = false)";


Could you please explain why you want to use eval for something like
this? What is your *actual* goal?

Paul Lalli
 
P

Paul Lalli

Mad said:
I see... thanks. I got it working.

However I have another question. Comparing booleans,

You are thinking of the wrong language. There is no such datatype in
Perl.
why would "TRUE eq true" evaluate to false?

If you mean "why would the string 'TRUE' not compare equally to the
string 'true'?", it's because the two strings are not equal. 'T' is
not the same as 't', 'R' is not the same as 'r', etc.
Also, how would I compare a string with caps insensitive? eg, "bob" !=
"Bob"

Don't compare the strings directly, compare their lowercase versions.

my $name1 = 'Bob';
my $name2 = 'bob';

if (lc($name1) eq lc($name2)) {
print "Match\n";
}
Also, how would you compare 2 dates?
http://search.cpan.org/~stbey/Date-Calc-5.4/Calc.pod


thanks again

#!/usr/local/bin/perl -- -*-perl-*-
#$exp = "(false eq false)"; RETURNS TRUE
$exp = "(FALSE eq false)"; RETURNS FALSE
#$exp = "(true eq true)"; RETURNS TRUE
#$exp = "(TRUE eq true)"; RETURNS FALSE
$str = "if ($exp) {\$answer=' evaluates to true';} else {\$answer='
evaluates to false';}";
eval $str or $answer = "answer evaluates to $@";
print $exp.$answer;

If you would enable strict and warnings, you would see what's actually
happening here. Asking hundreds of people around the world to do the
work of a machine is insulting at best.

add the lines
use strict;
use warnings;

right below your shebang.

Paul Lalli
 
M

Mad Scientist Jr

I see. I have one more question. I got it working fine, but when I turn
on "use strict" I get a bunch of new errors. What is this about?
Thanks...

#!/usr/local/bin/perl -- -*-perl-*-
use strict;
use warnings;
$exp = "( (17 ge 21) or (6.6 gt 6.5) ) and ('Bob' ne 'leon') and
('FALSE' eq 'false')";
$exp = lc($exp);
$str = "if ($exp) {\$answer=' evaluates to true';} else {\$answer='
evaluates to false';}";
eval $str or $answer = "answer evaluates to $@";
print $exp.$answer;

here is what it says when I try running with use strict:
Global symbol "$exp" requires explicit package name at
C:\Temp\perl_eval_4.pl line 4.
Global symbol "$exp" requires explicit package name at
C:\Temp\perl_eval_4.pl line 5.
Global symbol "$exp" requires explicit package name at
C:\Temp\perl_eval_4.pl line 5.
Global symbol "$str" requires explicit package name at
C:\Temp\perl_eval_4.pl line 6.
Global symbol "$exp" requires explicit package name at
C:\Temp\perl_eval_4.pl line 6.
Global symbol "$str" requires explicit package name at
C:\Temp\perl_eval_4.pl line 7.
Global symbol "$answer" requires explicit package name at
C:\Temp\perl_eval_4.pl line 7.
Global symbol "$exp" requires explicit package name at
C:\Temp\perl_eval_4.pl line 8.
Global symbol "$answer" requires explicit package name at
C:\Temp\perl_eval_4.pl line 8.
Execution of C:\Temp\perl_eval_4.pl aborted due to compilation errors.
 
P

Paul Lalli

Mad said:
I see. I have one more question. I got it working fine, but when I turn
on "use strict" I get a bunch of new errors. What is this about?

That's the whole point of using strict. It prevents you from doing
dangerous things in Perl. Specifically, it prevents you from: not
declaring your variables [1], using barewords as strings, and using
symbolic references.

Declare all your variables, using 'my', and surround all your strings
in quotes, and you'll see your errors disappear. (I don't think you
were using any symrefs, but I could be wrong).
#!/usr/local/bin/perl -- -*-perl-*-
use strict;
use warnings;
$exp = "( (17 ge 21) or (6.6 gt 6.5) ) and ('Bob' ne 'leon') and
('FALSE' eq 'false')";

my $exp = "( ( 17 ge .... ";
$exp = lc($exp);

my $answer;
$str = "if ($exp) {\$answer=' evaluates to true';} else {\$answer='
evaluates to false';}";

my $str = "if ($exp) ....";
eval $str or $answer = "answer evaluates to $@";
print $exp.$answer;

Paul Lalli

[1] It doesn't actually force you to declare your variables. In
actuality, all it does is forbid you from using global variables
without fully qualifying them. You still don't need to actually
declare global variables.
 
I

Ignoramus20015

I see. I have one more question. I got it working fine, but when I turn
on "use strict" I get a bunch of new errors. What is this about?
Thanks...

#!/usr/local/bin/perl -- -*-perl-*-
use strict;
use warnings;
$exp = "( (17 ge 21) or (6.6 gt 6.5) ) and ('Bob' ne 'leon') and
('FALSE' eq 'false')";
$exp = lc($exp);
$str = "if ($exp) {\$answer=' evaluates to true';} else {\$answer='
evaluates to false';}";
eval $str or $answer = "answer evaluates to $@";
print $exp.$answer;

here is what it says when I try running with use strict:

you should say

my ($str, $exp, $answer);

These warnings, however, have little to do with your problems.

i
 
M

Mad Scientist Jr

aha... i'm learning. i really should have put "newbie" in my subject
line. i haven't played with perl in many moons (1997 or so) and have no
recollection of needing to declare variables. i could probably do with
picking up a good perl book at this point or finding a good tutorial
site

thanks again

Paul said:
Mad said:
I see. I have one more question. I got it working fine, but when I turn
on "use strict" I get a bunch of new errors. What is this about?

That's the whole point of using strict. It prevents you from doing
dangerous things in Perl. Specifically, it prevents you from: not
declaring your variables [1], using barewords as strings, and using
symbolic references.

Declare all your variables, using 'my', and surround all your strings
in quotes, and you'll see your errors disappear. (I don't think you
were using any symrefs, but I could be wrong).
#!/usr/local/bin/perl -- -*-perl-*-
use strict;
use warnings;
$exp = "( (17 ge 21) or (6.6 gt 6.5) ) and ('Bob' ne 'leon') and
('FALSE' eq 'false')";

my $exp = "( ( 17 ge .... ";
$exp = lc($exp);

my $answer;
$str = "if ($exp) {\$answer=' evaluates to true';} else {\$answer='
evaluates to false';}";

my $str = "if ($exp) ....";
eval $str or $answer = "answer evaluates to $@";
print $exp.$answer;

Paul Lalli

[1] It doesn't actually force you to declare your variables. In
actuality, all it does is forbid you from using global variables
without fully qualifying them. You still don't need to actually
declare global variables.
 
P

Paul Lalli

Jim said:
Because Perl treats them as unequal strings. Perl does not have boolean
variables. It has values which may evaluate to true or false in boolean
expressions. The false values are undef, 0, '', and ().

And '0'

Paul Lalli
 
T

Tad McClellan

Mad Scientist Jr said:
aha... i'm learning. i really should have put "newbie" in my subject
line.


You really should have read the Posting Guidelines that are
posted here frequently.

.... and the guidelines specifically caution *against* putting
"newbie" in your subject line.

i haven't played with perl in many moons (1997 or so) and have no
recollection of needing to declare variables.


You do not need to declare variables to get a working Perl program.

You need to declare variables to get a program free of some
very common programming errors.



[ snip TOFU ]
 
T

Tad McClellan

Jim Gibson said:
The false values are undef, 0, '', and ().


No they're not.

And your including that last one indicates at least 2 significant
misconceptions (apart from missing the '0' false value).

1)
Parenthesis are not a "list constructor" (I assume your () represents
the empty list), they do not make a "list". They are often needed
for precedence reasons, which leads folks to the misconception
that they make a list.

Your last one is actually just another case of your first one:

my $empty = ();
print "\$empty is undef\n" unless defined $empty;

2)
A boolean value must be a scalar if you think about it for a minute.
You have to get to "one thing" so that you can see if that one
thing is one of the 4 false things or not.

So booleans are always in scalar context, and the docs
(perldoc -q "list and an array") say:

there's no such thing as a list in scalar context.





The false values are undef, 0, '', and '0'.
 
C

Ch Lamprecht

Jim said:
Thanks for the clarification. Yes, I was referring to the empty list
with (). My explanation to the OP was based on the fact that an empty
list evaluated as a boolean is false, since a list in scalar context
first evaluates to the length of the list, which is zero for an empty
list,

That's not true:

perl -e "$i= (1,2,0); print $i"
0

Christoph
 
P

Paul Lalli

Jim said:
Thanks for the clarification. Yes, I was referring to the empty list
with (). My explanation to the OP was based on the fact that an empty
list evaluated as a boolean is false

There is *no such thing* as a list evaluated as a boolean, because
boolean is a scalar context, and there's no such thing as a list in
scalar context.
, since a list in scalar context
first evaluates to the length of the list,

This is simply un-true. An *array* in scalar context returns the size
of that array. The comma operator used in scalar context does not
create a list at all. It simply evaluates its left-hand argument, and
evaluates-and-returns its right-hand argument.
which is zero for an empty
list, Thus, for all practical purposes, an empty list has a boolean
value of false. Is there any condition under which this is not true?

It is vacuously true, since there's no such thing as a list's "boolean
value"

$ perl -MData::Dumper -e'
sub fctn {
return ();
}
my $scalar = fctn();
my @array = fctn();
print Dumper(\$scalar, \@array);
if (fctn()) {
print "True\n";
} else {
print "False\n";
}
'
$VAR1 = \undef;
$VAR2 = [];
False

The () in the above subroutine are not a list. That return statement
is equivalent to:
return;
which returns undefined in scalar contexts (including boolean) and an
empty list in list context. You can see from the Dumper output of
$scalar that $scalar got the undefined value, not a 0. The if()
statement failed, but not because fctn() returned 0, but because it
returned undefined, just like it does in any other scalar context.

Hope this helps,
Paul Lalli
 
R

robic0

There is *no such thing* as a list evaluated as a boolean, because
boolean is a scalar context, and there's no such thing as a list in
scalar context.
There is no such thing as a 'boolean' in Perl !!!
This is simply un-true. An *array* in scalar context returns the size
of that array. The comma operator used in scalar context does not
create a list at all. It simply evaluates its left-hand argument, and
evaluates-and-returns its right-hand argument.
What is 'un-true' ?
You don't seem to know
It is vacuously true, since there's no such thing as a list's "boolean
value"
Again 'boolean' is not a type. True/false is not something you know
$ perl -MData::Dumper -e'
sub fctn {
return ();
}
my $scalar = fctn();
my @array = fctn();
print Dumper(\$scalar, \@array);
if (fctn()) {
print "True\n";
} else {
print "False\n";
}
'
$VAR1 = \undef;
$VAR2 = [];
False

The () in the above subroutine are not a list. That return statement
is equivalent to:
return;
which returns undefined in scalar contexts (including boolean) and an
empty list in list context. You can see from the Dumper output of
$scalar that $scalar got the undefined value, not a 0. The if()
statement failed, but not because fctn() returned 0, but because it
returned undefined, just like it does in any other scalar context.

Hope this helps,
Paul Lalli
Besides not understanding logic in Perl, your experience alone has helped
this individual.
 
P

Paul Lalli

robic0 said:
There is no such thing as a 'boolean' in Perl !!!

I did not say there was "a boolean". I said there was a boolean
context. Very different.
From `perldoc perldata`:
"A scalar value is interpreted as TRUE in the Boolean sense if it is
not the null string or the number 0 (or its string equivalent, "0").
The Boolean context is just a special kind of scalar context where no
conversion to a string or a number is ever performed."
What is 'un-true' ?

The line that I quoted. Do you have a reading comprehension problem?
You don't seem to know

Ah. You do have a reading comprehension problem. Thanks for clearing
that up.
Again 'boolean' is not a type.

Explain to me where I asserted that it is.
True/false is not something you know

This statement has no meaning.
Besides not understanding logic in Perl, your experience alone has helped
this individual.

You know, I understand all those words individually, but I can't figure
out how their ordering is supposed to form a coherent sentence.

Paul Lalli
 
T

Tad McClellan

Jim Gibson said:
My explanation to the OP was based on the fact that an empty
list evaluated as a boolean is false, since a list in scalar context
first evaluates to the length of the list,


No it doesn't.

A "list" is not an "array".

Did you read the FAQ I mentioned?

which is zero for an empty
list,


No, it is undef, not zero, as illustrated by the code I provided.

Thus, for all practical purposes, an empty list has a boolean
value of false.


An empty list cannot have a boolean value, because, once again,
there is no such thing as a list in scalar context!

What the list *evaluates to* when used in a scalar context depends
on what the list-operator's author defines it to do in scalar context.

Maybe return the number of elements in the list, maybe return the
last element of the list, maybe return the first element of the list,
maybe return the median over all of the list elements, maybe return
simply the string 'frobitz'.

You cannot predict what a list will evaluate to when used in a scalar
context, you have to read the docs to find out.
 
T

Tad McClellan

Jim Gibson said:
Thanks for the correction. I made the rookie mistake of mixing up
'list' and 'array'.


That is not at all a rookie mistake.

Much of the time the distinction doesn't matter, so even experienced
folks can be unaware of the distinction.

Of course that implies that some of the time the distinction _does_
matter, so spending time "getting it" is worthwhile.

Please s/list/array/g in the above explanation.


OK, but how do you fix the () part above (empty list) to
represent an empty array?

I was trying to explain to the OP that an empty array evaluated in
boolean context will evaluate to false.


Just in case it is clear as mud to other readers, let me restate that:

An empty array evaluated in a scalar context returns zero.

Zero in a boolean context (a special case of scalar context)
will evaluate to false.

I should have quit while I was
behind.


Oh no, I'll bet more that a few lurkers have been enlightened
by this discussion.



The thing to remember here is that we are concerned with _values_
(eg a list) not with _variables_ (eg an array).

We need a _value_ so that we can see if it is one of the 4 false
values or not.

If we need to do some evaluating before we can get to the value of
interest, so be it (such as array->count value, list->last value...).

Many times. The distinction between empty list and empty array seems
'empty' when talking about a boolean test.


I can concede that.

It doesn't really matter to
me whether they evaluate to undef, 0, or any other false value. Won't
they both evaluate to false in a boolean context? As long as

my @a = ();
if( @a ) {
print "true";
}else{
print "false";
}

produces "false", I am satisfied.


You are satisfied then. :)
 

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

Staff online

Members online

Forum statistics

Threads
474,161
Messages
2,570,892
Members
47,427
Latest member
HildredDic

Latest Threads

Top