
mhx
Enthusiast
Feb 12, 2002, 9:39 AM
Post #5 of 7
(63701 views)
|
Now, that's a tough one ;-) Let's have a look at (what I think is) Perl's parse tree of the expression in the first print statement:
++$num --$num \ / \ / ( - ) --$num \ / \ / ( + ) That tree is evaluated top-down, from left to right. Which means, the nodes are evaluated in the following order:
1 ++$num 2 --$num \ / \ / 3 ( - ) 4 --$num \ / \ / 5 ( + ) So, first of all $num is being incremented. The interesting part (and the one that I'm not sure about) is: Does Perl keep a copy of the incremented value in the node for further evaluation or does it only keep a reference to $num (which it already has)? Now, this is pure speculation, but in the favour of speed I would only keep a reference instead of creating a copy. Let's assume it is that way. Next, $num is being decremented. So it is back at zero now. The next node subtracts the values of its children, which are both zero (as we assume Perl keeps only references). And zero minus zero is obviously zero. If Perl would keep copies of pre(in|de)cremented values, the result would have been 1 instead. However, Perl has to create a new scalar value to hold the result. What happens next is that $num is autodecremented again and now holds a -1. The final node adds the zero and the -1, which results in -1. (In case Perl would make copies, the result would be 1 + (-1) = 0.) So the result should be either -1 or zero. My guess would be -1, because of the performance issue noted above. Now, let's move on to the second print statement. The parse tree is exactly the same, just that there are two postdecrements instead of the predecrements in the first expression:
1 ++$num 2 $num-- \ / \ / 3 ( - ) 4 $num-- \ / \ / 5 ( + ) The difference between a predecrement and a postdecrement is that Perl has to create a copy of the decremented value. (There's no option as for the predecrement.) Perl creates a copy, and the decrements the value. The following quote from the Camel Book, which I had a look into to see if there's a defined behaviour for expressions with multiple auto(in|de)crement operators, makes me believe that I'm right in my opinion that the pre(in|de)crement operators do not make copies:
The optimizer will notice this and optimize the post-increment into a pre-increment, because that's a bit faster to execute. What happens in the second expression is that $num (now with a value of -1) is being incremented. So it's zero now. Next, a copy of $num is created in the second node, and $num is decremented. That means $num is now -1, and when the third node is evaluated, the result is -1, since the first node still holds a reference to the recently decremented $num. Node 4 again created a copy of $num (-1) that is added in node 5 to the result of node 3 (also -1). So the result of the expression in the second print statement should be -2. As a conclusion, I'm pretty sure the results are -1 and -2, although I could also think of 0 and -1, if Perl would create copies for the pre(in|de)crement operations. -- mhx P.S.: I've run the code through perl right before I posted this and I was happy to see that I can't be very far from the truth. I'm going to investigate this a little further...
At last with an effort he spoke, and wondered to hear his own words, as if some other will was using his small voice. "I will take the Ring," he said, "though I do not know the way."-- Frodo
|