The up_by(), down_by(), etc. "shifting member functions" for Posn construct a new Posn modified from the existing one as specified. I've found that this doesn't match student's expectations that they will modify the Posn they are called on.
It also doesn't match my own expectations. If they were named from_up_by() similarly to the functions of Rect, I think that they would make more sense. Or if they actually modified they Posn they are called on.
Is it intentional behavior that the shifting member functions create a new Posn rather than modifying the one they are called on?