likbez has asked for the wisdom of the Perl Monks concerning the following question:
Looks like in tr function a scalar variable is accepted as the fist argument, but is not compiled properly into set of characters
$str1='abcde';
$str2='eda';
print "Test 1: strait set\n";
$diff1=$str1=~tr/$str2//;
$diff2=$str1=~tr/eda//;
print " diff1=$diff1, diff2=$diff2\n";
print "Test 2: complement set\n";
$diff1=$str1=~tr/$str2//c;
$diff2=$str1=~tr/eda//c;
print " diff1=$diff1, diff2=$diff2\n";
This produces in perl 5, version 26:
Test 1: strait set
diff1=0, diff2=3
Test 2: complement set
diff1=5, diff2=2
Obviously only the second result in both tests is correct.
Looks like only explicitly given first set is correctly compiled.
Is this a feature or a bug ?
Re: Strange behaviour of tr function in case the set1 is supplied by a variable
by Athanasius (Archbishop) on Nov 16, 2017 at 03:08 UTC
|
Hello likbez,
The transliteration operator tr/SEARCHLIST/REPLACEMENTLIST/ does not interpolate its SEARCHLIST, so in your first example the search list is simply the literal characters $, s, t, r, 2. See Quote and Quote like Operators.
Hope that helps,
| [reply] [d/l] [select] |
Re: Strange behaviour of tr function in case the set1 is supplied by a variable
by roboticus (Chancellor) on Nov 16, 2017 at 03:08 UTC
|
likbez:
Feature, per the tr docs Characters may be literals or any of the escape sequences accepted
in double-quoted strings. But there is no interpolation, so "$"
and "@" are treated as literals. A hyphen at the beginning or end,
or preceded by a backslash is considered a literal. Escape
sequence details are in the table near the beginning of this
section.
So if you want to use a string to specify the values in a tr statement, you'll probably have to do it via a string eval:
$ cat foo.pl
use strict;
use warnings;
my $str1 = 'abcde';
my $str2 = 'eda';
my $diff1 = 0;
eval "\$diff1=\$str1=~tr/$str2//";
print "diff1: $diff1\n";
$ perl foo.pl
diff1: 3
...roboticus
When your only tool is a hammer, all problems look like your thumb. | [reply] [d/l] [select] |
Re: Strange behaviour of tr function in case the set1 is supplied by a variable
by Anonymous Monk on Nov 16, 2017 at 03:09 UTC
|
Looks like in tr function a scalar variable is accepted as the fist argument, but is not compiled properly into set of characters
:)
you're guessing how tr/// works, you're guessing it works like s/// or m///, but you can't guess , it doesn't work like that, it doesn't interpolate variables, read perldoc -f tr for the details
| [reply] |
|
you're guessing how tr/// works, you're guessing it works like s/// or m///, but you can't guess , it doesn't work like that, it doesn't interpolate variables, read perldoc -f tr for the details
Houston, we have a problem ;-)
First of all that limits tr area of applicability.
The second, it's not that I am guessing, I just (wrongly) extrapolated regex behavior on tr, as people more often use regex then tr. Funny, but searching my old code and comments in it is clear that I remembered (probably discovered the hard way, not by reading the documentation ;-) this nuance several years ago. Not now. Completely forgotten. Erased from memory. And that tells you something about Perl complexity (actually tr is not that frequently used by most programmers, especially for counting characters).
And that's a real situation, that we face with Perl in other areas too (and not only with Perl): Perl exceeds typical human memory capacity to hold the information about the language. That's why we need "crutches" like strict.
You simply can't remember all the nuances of more then a dozen of string-related built-in functions, can you? You probably can (and should) for index/rindex and substr, but that's about it.
So here are two problems here:
1. Are / / strings uniformly interpreted in the language, or there is a "gotcha" because they are differently interpreted by tr (essentially as a single quoted strings) and regex (as double quoted strings) ?
2. If so, what is the quality of warnings about this gotcha? There is no warning issued, if you use strict and warnings. BTW,it looks like $ can be escaped:
main::(-e:1): 0
DB<5> $_='\$bba\$'
DB<6> tr/\$/?/
DB<7> print $_
\?bba\?
Right now there is zero warnings issued with use strict and use warnings enabled.
Looks like this idea of using =~ for tr was not so good, after all. Regular syntax like tr(set1, set2) would be much better. But it's to late to change and now we need warnings to be implemented. | [reply] [d/l] |
|
| [reply] [d/l] [select] |
|
|
|
What is a "// string"?
We have tr///ansliteration operator,
m//atch operator,
s///ubstitution operator,
qr//egex operator,
q//uote and qq//uote operator,
and only the firstr// one is rare.
A special warnings is moot?
Cause I mean you found out
without a special warnings tr/// wasnt doing what you wanted --
oh noes I made mistake, perl should have held my hand and kissed my booboo and spoon fed me wisdom and knowledge and wrote my program for me.
You can have Tr('list','replacement,'options') anytime you want,
simply stop shifting responsibility for your ignorance on the designers of the language.
I've been in the same exact boat more than once,
wrote something,
couldn't figure out what mistake I was making , posted about it,
what you have to do is learn from it,
take responsibility for your own knowledge,
write a perlcritic policy (its easy) to remind you in case you forget.
Information is not Knowledge. Knowledge is not Wisdom. Wisdom is not Truth. Truth is not Beauty. Beauty is not Love. Love is not Music. Music is the best.
| [reply] |
|
Re: Strange behaviour of tr function in case the set1 is supplied by a variable
by ww (Archbishop) on Nov 16, 2017 at 03:16 UTC
|
Same results in AS 5.24 under Win7x64.
Suspected problem might have arisen from lack of strict, warnings. Wrong, same results BUT using both remains a generally good idea.
Also wondered if compiling (with qr/.../) might change the outcome. Wrong again, albeit with variant (erroneous) output.
Correct me if I'm wrong, guessing that "strait" is a typo or personal shortening of "straight."
Update: Now that I've seen earlier replies... ouch, pounding forehead into brick wall!
“Ah, you don’t have to know everything. You just have to know where to find it.” John Brunner'
If I've misconstrued your question or the logic needed to answer it, I offer my apologies to all those electrons which were inconvenienced by the creation of this post.
| [reply] [d/l] |
Re: Strange behaviour of tr function in case the set1 is supplied by a variable
by likbez (Sexton) on Nov 16, 2017 at 03:10 UTC
|
With eval statement works correctly. So it looks like $ is treated by tr as a regular symbol and no warning are issued.
$statement='$diff1=$str1'."=~tr/$str2//;";
eval($statement);
print "With eval: diff1=$diff1\n";
that will produce:
With eval: diff1=3
</code> | [reply] [d/l] |
|
|