Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

Re: tr operator in eval -- updated

by haukex (Archbishop)
on Sep 26, 2020 at 08:37 UTC ( #11122233=note: print w/replies, xml ) Need Help??

in reply to tr operator in eval -- updated

The example on p.76 of the camel book

What edition of the book are you looking at? In the fourth edition, the example that I think you're referring to is on page 191, and in the third edition, the page number is similarly high. From the 4th ed, it's:

$count = eval "tr/$oldlist/$newlist/"; die if $@; # propagates exception from illegal eval contents
a) eval " ... code ... " as shown in the book gives an eval error message. and eval "tr/$oldlist/$newlist/;" This does not work.

No, there is nothing wrong with that example code in the second, third, and fourth editions of the book. (Nitpicks: under strict, the variables obviously need to be predeclared, and the if $@ pattern is not recommended.)

This means that the code you're running is not exactly the code from the book, and you haven't shown an example of the code that does produce the error you're referring to, nor the error message itself. How do I post a question effectively? and I know what I mean. Why don't you?

even putting the code in braces it does not work.

There is a significant difference between eval STRING and eval BLOCK. The latter is basically just an exception trapping mechanism, it does not delay the compilation of the code inside the block until runtime, which is what the former does, and it is required in this case, since as the book explains, the pattern is built at compile time.

The problem is that $kards should be set to the result of the eval execution, not put inside the eval execution.

Well, that at least gives a hint as to what might have been going wrong. So you probably wrote eval "$kards = $bad =~ tr/$card//;"? Note that what eval STRING does is compile a string of Perl code and execute it. If you take a close look at the string you're giving it, "$kards = $bad =~ tr/$card//;", note that since it's in double quotes, all the variables inside are interpolated. In other words, using the values you've shown here, the string you're actually handing to eval to compile and run is '-99 = AKQJT98765432KKKK =~ tr/K//;', which of course doesn't make sense. You meant for eval to execute the Perl code '$kards = $bad =~ tr/K//;', i.e. only the value of $card should be interpolated, which means you need to prevent the other two variables from being interpolated, for example by putting backslashes in front of the sigils, as in "\$kards = \$bad =~ tr/$card//;".

This also means that your second example code, $kards = eval "$bad =~ tr/$card//;";, has the same issue, because you're asking Perl to execute the piece of code 'AKQJT98765432KKKK =~ tr/K//;'. This only happens to work if you're not using strict, because Perl is taking AKQJT98765432KKKK as a "bareword", a feature that is not allowed under strict "subs". And since one shoud always Use strict and warnings, you should escape $bad in this code as well.

Replies are listed 'Best First'.
Re^2: tr operator in eval -- updated
by pgmer6809 (Sexton) on Sep 27, 2020 at 02:34 UTC
    Thank you very much for the detailed explanation haukex. It is very complete. To answer some of your other questions I am referring to 2nd Edition (1999) of Camel book. The example on p.76 is in the explanation of tr, not in the explanation of eval. the literal text from that page is :  eval "tr/$oldlist/$newlist/"; die $@ if $@; I knew that perl had progressed some since 1999 but it did not occur to me that there would of course be further editions of the Camel book. Thanks again. pgmer6809

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11122233]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (1)
As of 2023-01-28 00:12 GMT
Find Nodes?
    Voting Booth?

    No recent polls found