Ok, you're right! But it's not a bug.
Your problem comes from the fact [expr] first computes the expression corresponding to the right-most outlet (the 'y' value in your case), which (if done 'naively') immediately updates the [value y].
Then it computes the left-most outlet expression (the 'x' value); at this point, the formula "(x*cos(theta))-(y*sin(theta))" uses the previous 'x' value but the UPDATED 'y' value. Hence the "wrong" result.
So what you need is to ensure that [value y] is NOT updated before the 'x' value is computed.
One solution is to store the 2nd outlet output into the right outlet of a [f], that you bang when the first outlet fires.
Another is to use a [pack f f], which is [unpack]ed only when the 'x' value comes to its first inlet. This solution easily supports more than 2 outlets.
[expr compute_x(x, y);
compute_y(x, y)]
| |
[pack f f ]
|
[unpack f f]
| |
[v x] [v y]
In pd:
#N canvas 145 73 450 335 12;
#X obj 26 176 expr (x*cos(theta))-(y*sin(theta)) \; (x*sin(theta))+(y*cos(theta));
#X msg 24 38 1 0 1.5708;
#X obj 24 64 unpack f f f;
#X obj 105 88 v theta;
#X obj 64 90 v y;
#X obj 24 88 v x;
#X floatatom 26 299 9 0 0 0 - - - 0;
#X floatatom 93 299 10 0 0 0 - - - 0;
#X obj 103 271 v y;
#X obj 37 271 v x;
#X obj 26 149 bng 20 250 50 0 empty empty empty 0 -10 0 12 #fcfcfc #000000 #000000;
#X obj 26 217 pack f f, f 35;
#X obj 26 242 unpack f f;
#X text 23 16 1: init;
#X text 24 127 2: iterate;
#X connect 0 0 11 0;
#X connect 0 1 11 1;
#X connect 1 0 2 0;
#X connect 2 0 5 0;
#X connect 2 1 4 0;
#X connect 2 2 3 0;
#X connect 10 0 0 0;
#X connect 11 0 12 0;
#X connect 12 0 6 0;
#X connect 12 0 9 0;
#X connect 12 1 7 0;
#X connect 12 1 8 0;