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; 

Antoine

Le dim. 28 déc. 2025 à 16:25, Hrvoje Radnic <hrvojeradnic@yahoo.com> a écrit :
Thank you Antoine for help!
It works, but only once. If I feed the results from [expr] into [v x] and [v y], it starts to act like in my original post. Maybe I completely missed the purpose of [value] object. My idea was to set only the initial values and then advance with 90 degrees of rotation from updated x and y values with every bang the [expr] object receives.