|No such thing as a small change|
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:
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.