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

Hi

according to perlop#s/PATTERN/REPLACEMENT/ a double eval isn't a double eval but the eval of an interpolation

e Evaluate the right side as an expression. ee Evaluate the right side as a string then eval the result.

At least that's how I understand the distinction between "evaluate as an expression" and "evaluate as a string"...

Problem is that I can't see this distinction, ee produces just

eval ( eval 'RHS' )

eval do { RHS } ¹

for me and not

eval "RHS".

Or what is meant here, if "evaluate as a string" isn't supposed to mean "string resp. var interpolation", what else?

some snippets as demonstration

DB<135> $_='x' => "x" DB<136> $a='$b'; $b="B" => "B" DB<137> s/x/$a.$a/r # -> "$a.$a" (interpolation) => "\$b.\$b" DB<138> s/x/$a.$a/re # -> eval '$a.$a' => "\$b\$b" DB<139> s/x/$a.$a/ree # -> eval "\$b\$b" not eval "\$b.\$b" Scalar found where operator expected at (eval 106)[(eval 105)[multi_pe +rl5db.pl:644]:2] line 1, near "$b$b" ...

but

DB<140> s/x/$a.'.'.$a/ree # -> eval "\$b.\$b" => "BB" DB<141> s/x/$a.'.'.$a/re # -> eval '$a.\'.\'.$a' => "\$b.\$b" DB<142> s/x/$a.'.'.$a/r # -> "$a.'.'.$a" => "\$b.'.'.\$b" DB<143> eval "\$b.'.'.\$b" # what perldoc predicts for line 140 => "B.B"

Cheers Rolf

(addicted to the Perl Programming Language and ☆☆☆☆ :)

¹) updated: the RHS is precompiled, but eval 'RHS' means runtime compilation

Replies are listed 'Best First'.
Re: perldoc of s///ee wrong or just misleading?
by dave_the_m (Monsignor) on Dec 28, 2014 at 16:03 UTC
    If hypothetically $& was assignable to, then the following are roughly equivalent:
    s/X/Y/ /X/ && $& = "Y" s/X/Y/e /X/ && $& = Y s/X/Y/ee /X/ && $& = eval Y

    Dave.

      I know what you mean and I agree about what is happening, but the perldoc is wrong!

      it should say

      ee Execute right side as code then eval the resulting string.

      NOT

      ee Evaluate the right side as a string then eval the result.

      see:

      lanx@lanx-1005HA:~$ perl -MO=Terse -e ' s/(x)/$1.$1/ree ' LISTOP (0x9f99668) leave [1] OP (0x9fa6040) enter COP (0x9f99688) nextstate PMOP (0x9fa2f20) subst LOGOP (0x9fa2e20) substcont UNOP (0x9fa2f00) entereval [256] # --- string eval of resu +lt UNOP (0x9fa2c58) null LISTOP (0x9fa2be8) scope # --- precompiled $1.$ +1 OP (0x9fa1b28) null [181] BINOP (0x9fa2c38) concat [3] UNOP (0x9fa2cb8) null [15] PADOP (0x9fa2d30) gvsv GV (0x9fd4c90) + *1 UNOP (0x9fa2c18) null [15] PADOP (0x9fa2c98) gvsv GV (0x9fd4c90) + *1 -e syntax OK

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

      > If hypothetically $& was assignable to, then the following are roughly equivalent:

      maybe better

      s/PAT/STR/ <=> m/PAT/ && $& = "STR"; s/PAT/CODE/e <=> m/PAT/ && $& = do {CODE}; s/PAT/CODE/ee <=> m/PAT/ && $& = eval do {CODE}; s/PAT/CODE/eee <=> m/PAT/ && $& = eval eval do {CODE}; ... and so on

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: perldoc of s///ee wrong or just misleading?
by LanX (Saint) on Dec 28, 2014 at 16:00 UTC
    running B::Terse shows that the RHS is even precompiled and not evaluated at runtime:

    lanx@lanx-1005HA:~$ perl -MO=Terse -e 's/(x)/$1.$1/re' LISTOP (0x8eb6668) leave [1] OP (0x8ec3040) enter COP (0x8eb6688) nextstate PMOP (0x8ebff20) subst LOGOP (0x8ebff00) substcont UNOP (0x8ebfbe8) null LISTOP (0x8ebfc38) scope OP (0x8ebeb28) null [181] BINOP (0x8ebfc18) concat [3] UNOP (0x8ebfd30) null [15] PADOP (0x8ebfe20) gvsv GV (0x8ef1c90) *1 UNOP (0x8ebfc98) null [15] PADOP (0x8ebfcb8) gvsv GV (0x8ef1c90) *1

    That's why this rather ill construction works

    lanx@lanx-1005HA:~$ perl -e 'sub bla { s/x/BEGIN{print "compiletime\n" +}/e }' compiletime

    But still doesn't make the perldocs clearer...

    Cheers Rolf

    (addicted to the Perl Programming Language and ☆☆☆☆ :)

Re: perldoc of s///ee wrong or just misleading? (read more)
by Anonymous Monk on Dec 28, 2014 at 20:52 UTC

    Yes the wording is odd, but like a lot of perl docs, if you keep reading you will get all the details, like: A second e modifier will cause the replacement portion to be evaled before being run as a Perl expression.

    I once wrote

    s/regex/STRING /e
    means replace that matched by regex with string
    s/regex/CODEHERE/e
    means replace that matched by regex with result of code; the e in s///e tells the s///ubstitution operator that the s//CODEHERE/e is code and not a string
    s/regex/CODEHERE/e
    means treat CODEHERE string as code
    s/regex/CODEHERE/ee
    means treat CODEHERE string as code, and treat the return value of that code as code
    s/regex/CODEHERE/ee
    means s/regex/eval CODEHERE/e

    One time I even tried to explain this way :)

    my $string = 'string'; ## s/string/replacement/; $string->substitute( 'pattern', 'replacement' ); ## s/string/codehere/e; $string->substitute( 'pattern', sub { ... } ); ## s/string/codehere/ee; $string->substitute( 'pattern', sub { eval ... } ); ## s/string/codehere/eee; $string->substitute( 'pattern', sub { eval eval ... } );

      Consider

      s/.../$1' $2"/

      More accurate:

      $string->substitute( qr/pattern/, sub { qq/replacement/ } );
Re: perldoc of s///ee wrong or just misleading?
by Anonymous Monk on Dec 28, 2014 at 17:16 UTC
    Yes you're right. The wordage is misleading. '/e' and the initial 'e' in '/ee' do the same thing, but the documentation gives an impression that they are somehow different.
      I do not like to admit it, but this is one area where I still depend on trial-and-error.
      Bill
Re: perldoc of s///ee wrong or just misleading?
by ikegami (Patriarch) on Dec 29, 2014 at 17:58 UTC
    SubstitutionExpression evaluated for each matchIf the operator was implemented as a function
    s/pat/repl/qq/repl/subst($_, qr/pat/, sub { qq/repl/ })
    s/pat/repl/ereplsubst($_, qr/pat/, sub { repl })
    s/pat/repl/eeeval(repl)subst($_, qr/pat/, sub { eval(repl) })

    In both of the last two cases, repl is evaluated as a scalar expression and its result is expected to be a string.

    The docs are incorrect or confusing.

      > repl is evaluated as a scalar expression

      Not sure, do you mean string eval?

      Cheers Rolf

      (addicted to the Perl Programming Language and ☆☆☆☆ :)

        I don't understand the question — neither the whole nor any part of what I said can be replaced by "string eval" and still make sense — but I did say what I meant to say.