A Perl script was written a few days ago :? Operator encountered a very strange problem
$ Data-> {$ id}-> {'Total '}?
$ Data-> {$ id}-> {'ratio '} = sprintf ("%. 2f % ", 100 * $ data-> {$ id}-> {'succ'}/$ data-> {$ id}-> {'Total '}):
$ Data-> {$ id}-> {'ratio '} = 'n'/';
My intention is that if $ data-> {$ id}-> {'Total'} is undefined, the ratio is not calculated, and the ratio value is assigned to N/A. This statement is equivalent
If ($ data-> {$ id}-> {'Total '}){
$ Data-> {$ id}-> {'ratio '} = sprintf ("%. 2f % ", 100 * $ data-> {$ id}-> {'succ'}/$ data-> {$ id}-> {'Total '});
} Else {
$ Data-> {$ id}-> {'ratio '} = 'n'/';
It is strange that, no matter whether total has ratio defined or not, the result is N/A. But if ...... Else ...... There is no problem with the statement. It is really hard for me to think about it.
Run to query the Perl document? : Operator number is interpreted
Ternary ''? : ''Is the conditional operator, just as in C. It works much like an if-then-else. If the argument before? Is true, the argument before the: is returned, otherwise the argument after the: is returned.
It looks likeReturn the argumentSo suddenly I came up with an idea and added brackets to the front and back ......
$ Data-> {$ id}-> {'Total '}?
($ Data-> {$ id}-> {'ratio '} = sprintf ("%. 2f % ", 100 * $ data-> {$ id}-> {'succ'}/$ data-> {$ id}-> {'Total '})):
($ Data-> {$ id}-> {'ratio '} = 'n'/');
...... That's right. Since it's return the argument, I 've changed the way:
$ Data-> {$ id}-> {'ratio '} = $ data-> {$ id}-> {'Total '}?
Sprintf ("%. 2f % ", 100 * $ data-> {$ id}-> {'succ'}/$ data-> {$ id}-> {'Total '}):
'N'/';
Although both of the following methods can be understood, it is indeed a correct method. But why is the result of the first method incorrect? Does return the argument mean not to perform the assignment operation there?
I wrote a simple small program for testing.
1 #! /Usr/bin/perl
2
3 use strict;
4
5 my $ Total = 1;
6 my $ rval;
7
8 $ total?
9 $ rval = $ total:
10 $ rval = 'n'/';
11
12 Print $ rval, "/N ";
13
14 if ($ total ){
15 $ rval = $ total;
16} else {
17 $ rval = 'n'/';
18}
19
20 Print $ rval;
The running result shows that no matter what value is assigned to $ total in row 5th ...... Including 1, "ABC", "true", UNDEF, etc. The first print of the execution result is N/A. Is it $ total? Is it not equivalent to if ($ total?
By accident, we found a method to verify how Perl parses these statements internally:
Perl-mo = deparse,-p-e '$? $ B = 1: $ B = 2 ;'
The output result is unexpected:
($? ($ B = 1): $ B) = 2 );
Now the situation is quite obvious. It turns out to be an operator priority problem! In Perl, the ternary operator :? The priority ratio is higher than the value =. What is the Priority Ratio in C? : High. This is almost beyond common sense, habits, and characteristics, and is also a trap that is easy to fall.
The solution is also simple, written as $? ($ B = 1): ($ B = 2.
This further confirms the programming rule: in complex operator operations, brackets are used to identify the priority of each operation, even if you think you understand the order of operation.