The path of least resistance as a developer is to just eval the string, letting Perl do the work. But that can be fraught with peril if the input is not completely under your control and known to be syntactically sound, and free from bad behavior. Here's an example:
while( <DATA> ) { chomp; print "( $_ ) = ( ", eval($_), " )\n"; }
But this is almost certainly a bad idea, since your data could contain any arbitrary Perl code -- and we all know how much trouble one can get into with arbitrary Perl code.
So the developer seeking the path of least resistance might then think to gravitate toward the Safe module. Using that module one can cherry-pick those operations that are to be considered well-behaved and benign enough to allow for their execution; a constrained subset of arbitrary user code. And that code is executed in a sort of sand box that minimizes its ability to interact with the underlying system. Safe seems like a fairly safe approach.
But it's really going in the wrong direction. The end goal isn't to get perl to parse and execute a safe subset of Perl. The goal is for your script to parse, comprehend, and evaluate mathematical equations. This is one of those things that every first-year CS student takes on at one point or another. A minimal implementation is discussed within the first couple of chapters in SICP. MJD works his reader through a simple implementation early-on in Higher Order Perl. There may be (though I don't remember for sure) a discussion of an implementation in Mastering Algorithms with Perl, as well. The trick is to tokenize, parse into a tree, and traverse the tree while applying the appropriate operators to the appropriate factors.
While this isn't terribly complex, it's not really worth doing all over again unless you're trying to learn how to do it. It's been done a million times before. And as it turns out, there's at least one (and probably many) solutions on CPAN. One I noticed is authored by mortiz: Math::Expression::Evaluator. This module provides a simple interface to a set of black boxes that do all of the work for you. Here is an example:
use Math::Expression::Evaluator; while( <DATA> ) { chomp; my $m = Math::Expression::Evaluator->new; eval { my $p = $m->parse($_); print "( $_ ) = ( ", $p->val, " )\n"; 1; } or warn "Unable to resolve expression ($_).\n"; } __DATA__ 1+2 1 + 2 2 * 2 + 4 asdf#@fg
When you run that, you get:
( 1+2 ) = ( 3 ) ( 1 + 2 ) = ( 3 ) ( 2 * 2 + 4 ) = ( 8 ) Unable to resolve expression (asdf#@fg).
No need to implement your own, no need to deal with string eval, or Safe. Done. ;)
Dave
In reply to Re: converting from str to int
by davido
in thread converting from str to int
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |