Re: When is 'eval' too inefficient?
by Corion (Patriarch) on Oct 12, 2007 at 12:59 UTC
|
Using eval is almost always overkill, especially when your data already has a well-defined structure. In your case, you seem to be using floating point numbers, so you might want:
my $increment = ($var1 + 0) || $var2;
$value += $increment;
If your numbers are actually strings being read in from a file, an explicit string comparison might be even more explicit:
my $increment = ($var1 ne '0.00') ? $var1
: $var2;
The rule of thumb is to always avoid the string form of eval, because there are almost always more efficient ways around it unless you need to parse arbitrary Perl code. | [reply] [d/l] [select] |
|
|
You're right about the floating numbers--it's never the case that one of the variables would be undefined. The use of "+0" is precisely the solution, but dare I say, an inelegant one. If I can say int $var1, I think there should be an equivalent counterpart for real numbers, as in real $var1 or float $var1.
Though the problem is solved, I'm still curious about the broader question of eval that I originally asked: is there a rule of thumb as to how inefficient it may be? Are there suggestions about when it's best to avoid it, and best to use it?
| [reply] [d/l] [select] |
|
|
To argue that Perl should provide a function to convert a scalar to a float because it provides a function to convert a scalar to an integer is a valid argument, but the premise is false. Perl doesn't have a function that converts a scalar to an integer.
int implements the mathematical function. It doesn't necessarily return an integer in the C sense of the word. For example, here's an example where int returns a float (NV):
>perl -MDevel::Peek -e"Dump int(2**32);"
SV = NV(0x184ac1c) at 0x226be4
REFCNT = 1
FLAGS = (NOK,pNOK)
NV = 4294967296
Type conversion is always done implicitely in Perl.
If Perl needs a string, the scalar will be coerced into a string.
If Perl needs a number, the scalar will be coerced into a number.
If Perl needs a boolean, the scalar will be coerced into a boolean.
etc.
Of course, you are free to produce your own conversion routines.
sub to_string { "$_[0]" }
sub to_num { 0+$_[0] }
sub to_bool { !!$_[0] }
etc.
| [reply] [d/l] [select] |
|
|
Person 1: This is my favorite horse.
Person 2: Isn't that your only horse?
In the general sense, eval is the most efficient function. There's simply no alternative.
In specific situations where there is an alternative, the alternative is probably more efficient (and safer and more maintainable). You'll have to benchmark the two for more details.
| [reply] [d/l] |
Re: When is 'eval' too inefficient?
by ikegami (Patriarch) on Oct 12, 2007 at 13:16 UTC
|
Be careful when you omit parens. You got lucky because of eval's prototype, but other functions aren't as forgiving.
eval $var1 || eval $var2;
means
eval($var1) || eval($var2);
For non-exceptional functions,
func $var1 || func $var2;
means
func($var1 || func($var2));
| [reply] [d/l] [select] |
Re: When is 'eval' too inefficient?
by ikegami (Patriarch) on Oct 12, 2007 at 13:07 UTC
|
The problem with eval EXPR is not efficiency, it's danger. It's harder to maintain and debug, and it's more successible to injection attacks and bugs.
| [reply] [d/l] |
Re: When is 'eval' too inefficient?
by Fletch (Bishop) on Oct 12, 2007 at 13:00 UTC
|
$ perl -le '$var1 = "0.00"; $value += ($var1+0) || 99; print $value'
99
And your use of eval there is string eval so yes that's expensive and not really a good idea.
| [reply] [d/l] |
Re: When is 'eval' too inefficient?
by dsheroh (Monsignor) on Oct 12, 2007 at 14:21 UTC
|
As I read your question, it looks like you're trying to add $var1 if it's defined or $var2 if it isn't, but you're getting tripped up by testing whether $var1 is true instead.
If my interpretation is correct, then test for definedness with defined:
$value += defined $var1 ? $var1 : $var2;
| [reply] [d/l] [select] |
Re: When is 'eval' too inefficient?
by eyepopslikeamosquito (Archbishop) on Oct 12, 2007 at 22:51 UTC
|
| [reply] |
Re: When is 'eval' too inefficient?
by codeacrobat (Chaplain) on Oct 12, 2007 at 19:55 UTC
|
I eagerly await the "defined" and "defined-or" operator of Perl 5.10
$val = expr1 // expr2;
$val //= expr3;
This will fix many conditional assignment bugs involving checks on zero.
print+qq(\L@{[ref\&@]}@{['@'x7^'!#2/"!4']});
| [reply] [d/l] [select] |
|
|
The problem value '0.00' is defined. // would still give the undesired result.
| [reply] [d/l] [select] |
Re: When is 'eval' too inefficient?
by DrHyde (Prior) on Oct 15, 2007 at 11:37 UTC
|
Have you benchmarked it? That will tell you whether using eval is faster or slower than just adding 0 to force things to be numeric.
Have you profiled it? That will tell you whether you should care.
| [reply] |