Print

Print


Not hearing a peep from the peanut gallery :-( I'm inclined to make  
the (B) modifications.  Going once, going twice?

Sean

On Oct 27, 2009, at 7:41 PM, Sean Luke wrote:

> I'm facing a tough decision on Double2D which could affect the  
> entire community and so I'm interested in some feedback.
>
> I've been going through the physics2d engine and doing some cleanup  
> and one thing that could really help in that cleanup is to add some  
> functions to Double2D which are presently only in MutableDouble2D,  
> but to do so in such a way that Double2D's version would have  
> somewhat different semantics.
>
> MutableDouble2D has four kinds of ways of "adding":
>
> MutableDouble2D m1, m2, m3;  // 2d vectors
> double v;  // a scalar
>
> m1.addIn(m2);   // m1 <- m1 + m2, return m1
> m1.addIn(v);    // m1 <- m1 + v (at all slots in m1), return m1
>
> m1.add(m2, m3); // m1 <- m2 + m3, return m1
> m1.add(m2, v);  // m1 <- m2 + v (at all slots in m1), return m1
>
> The use of "add" in this context is unfortunate, I know.  It's going  
> to cause problems in a second.  But originally my idea was to enable  
> stuff like this:
>
> m1 = new MutableDouble2D().add(m2, m3).multiplyIn(v).normalize();
>
> Which does
> 	m1 <- normalize((m2 + m3) * v)
>
> ... but doesn't do any new allocations at all, because at each step  
> we just overwrite the variables inside the MutableDouble2D we created.
>
> Okay, so that's cute.  The problem comes when I want to add similar  
> functionality to Double2D.  I can't implement an "addIn" method  
> because Double2D is IMMUTABLE.  Instead, I'd do something like this:
>
> Double2D d1, d2, d3;
> double v;
>
> d1 = d2.add(d3).mutiply(v).normalize();
>
> This does the same thing but at each step a new Double2D is  
> created.  For example,
>
> d1.add(d2);	// new d <- d1 + d2, return d
>
> That's a good, easy to understand functional style which is much  
> less convoluted than the MutableDouble2D approach, BUT it allocates  
> lots of Double2Ds, which isn't particularly efficient, though it's  
> not horrible.  So it's a useful functionality to have in Double2D.
>
> The problem is that the semantics are somewhat different than  
> MutableDouble2D's semantics, in which the original object is  
> OVERWRITTEN.  This is particularly obvious in the normalize()  
> method, which in MutableDouble2D normalizes the actual  
> MutableDouble2D, but for Double2D would produce a new Double2D (it's  
> have to).
>
> Also MutableDouble2D's add(...) method, for example, takes two  
> arguments and has totally different semantics than Double2D's  
> add(...) method would.
>
> I'm trying to nail down what options I have.  One choice I have been  
> mulling over is to add methods to Double2D like add(d) [note one  
> argument], multiply(v), etc., and then also create similar  
> MutableDouble2D methods with the same names.  But the question is  
> how the MutableDouble2D methods should work.  Should they (A)  
> produce NEW MutableDouble2D instances or (B) overwrite the existing  
> MutableDouble2D instance, like other MutableDouble2D methods  
> presently do?
>
> (A) is more semantically consistent with the proposed new Double2D  
> methods.
>
> (B) is semantically consistent with the existing MutableDouble2D  
> methods.
>
> I'm trying to follow the principle of least surprise but I don't  
> know which of these would have less surprise.   normalize() in  
> particular will *have* to be case (B).  There's no way around it.   
> Which has been nudging me to wards doing (B).   A third option would  
> be to just create Double2D methods and not create ANY equivalent  
> MutableDouble2D methods.
>
> The decision made here will have a long-standing effect on use of  
> these classes, and they're so integral to MASON that I want to be  
> very very careful.  Backward compatability will be retained but I am  
> concerned about making things weird in the future.
>
> So I'd really appreciate some opinions on the matter.
>
> Sean
>
>