Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

interpolating operators within strings

by abualiga (Scribe)
on Apr 14, 2013 at 01:16 UTC ( [id://1028580]=perlquestion: print w/replies, xml ) Need Help??

abualiga has asked for the wisdom of the Perl Monks concerning the following question:

Hi there, I'm trying to understand interpolation of operators within strings. Specifically, can mathematical operators be interpolated within strings and evaluated as operators. Below is some example code to make my question clear. Many thanks!

my @ops = ( '-', '+', '*', '/' ); for( @ops ) { my $a = "2 $_ 2"; say $a; }

Is it possible iterate over these operations and perform calculations?

Replies are listed 'Best First'.
Re: interpolating operators within strings
by NetWallah (Canon) on Apr 14, 2013 at 01:34 UTC
    Try using "eval" : see "perldoc -f eval".

    my $a = eval "2 $_ 2";
    This is not considered "safe" because it is possible to inject unwanted code into the eval string.
    It is fine for testing purposes.

                 "I'm fairly sure if they took porn off the Internet, there'd only be one website left, and it'd be called 'Bring Back the Porn!'"
            -- Dr. Cox, Scrubs

Re: interpolating operators within strings
by kcott (Archbishop) on Apr 14, 2013 at 02:16 UTC

    G'day abualiga,

    As ++NetWallah points out, eval can be unsafe.

    If your eval code started off like this:

    $ perl -Mstrict -Mwarnings -E 'say eval for map { "12 $_ 3" } qw{+ - * + / % **}' 15 9 36 4 0 1728

    Using a despatch table like this is a safer option.

    $ perl -Mstrict -Mwarnings -E ' my %op_hash = ( q{+} => sub { $_[0] + $_[1] }, q{-} => sub { $_[0] - $_[1] }, q{*} => sub { $_[0] * $_[1] }, q{/} => sub { $_[0] / $_[1] }, q{%} => sub { $_[0] % $_[1] }, q{**} => sub { $_[0] ** $_[1] }, ); say for map { $op_hash{$_}->(12, 3) } qw{+ - * / % **}; ' 15 9 36 4 0 1728

    And you can add your own sanity checks:

    $ perl -Mstrict -Mwarnings -E ' my %op_hash = ( q{+} => sub { $_[0] + $_[1] }, q{-} => sub { $_[0] - $_[1] }, q{*} => sub { $_[0] * $_[1] }, q{/} => sub { die "Divide by zero!" if $_[1] == 0; $_[0] / +$_[1] }, q{%} => sub { $_[0] % $_[1] }, q{**} => sub { $_[0] ** $_[1] }, ); say for map { $op_hash{$_}->(12, 0) } qw{+ - * / % **}; ' Divide by zero! at -e line 6.

    I don't know what context you're intending to use this in: the overload pragma may be of some use.

    Update: s/unsafe:/unsafe./ and added "If your eval code started off like this: "

    -- Ken

      How is anything in your example unsafe? I am reminded of MJD's righteous takedown of a similar superstitious warning (see slide 31).
        Thanks educated_foo, I'd not seen that presentation before, and it's well worth a read :)

      Your insight is much appreciated! I was trying to do addition and subtraction of two lists of paired numbers and wanted to avoid separate loops.

        Well, in that case, you might be better off with the pairwise function of List::MoreUtils:

        $ perl -Mstrict -Mwarnings -E ' use List::MoreUtils qw{pairwise}; my @x = 0 .. 3; my @y = map { 10 + $_ } @x; say for pairwise { "$a + $b = " . ($a + $b) . "; $b - $a = " . ($b - $a) } @x, @y; ' 0 + 10 = 10; 10 - 0 = 10 1 + 11 = 12; 11 - 1 = 10 2 + 12 = 14; 12 - 2 = 10 3 + 13 = 16; 13 - 3 = 10

        Note how $a holds @x elements and $b holds @y elements. These ($a & $b) are the same special variables used by sort, so don't declare them; they're described in perlvar - SPECIAL VARIABLES - General Variables. You can use them in either order: cf. $a + $b and $b - $a.

        -- Ken

      If you first use a regex to remove anything that isn't an operator, a number format, or a space, then it's perfectly safe to eval from there.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1028580]
Approved by kcott
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (3)
As of 2024-04-19 01:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found