Weird behavior on allocation...what's going on?

A

Alex Hunsley

Oliver said:
I think one reason Chris suggested the q3 = q1.add(q2) syntax is that
it's pretty idiomatic of Java. Strings and BigInteger, for example, both
follow that pattern. So a Java programmer whose is used to using Strings and
BigInteger can quickly guess what the syntax is for your Quaternion classes.

I've always found that idiom a little annoying in a purist sense,
although you're right in that it is a standard. I think that on first
look, when you're not used to this standard, you might expect an
instance method like q1.add(q2) to actually have an effect on the value
of q1 - but it doesn't (it just returns the result). And I know that
many people do trip up over this assumption, initially.
To me, Quaternion.add(q1, q2) is clearer - a result will be returned.
That said, notice that Chris suggested a way so that both formulations
are available (i.e. q3 = q1.add(q2) would be equivalent to q3 =
Quaternion.add(q1, q2)) with minimal hassle.

Yup, if space isn't a big limit, I prefer implementing both forms when
writing such a class, and giving the user the choice.
lex
 
Z

Zerex71

Greetings,
I'm working on an application which will be very math-intensive, and
requires the use of mathematical constructs known as quaternions.
They are basically 4-vectors and that's all you need to know for this
discussion.
[...]
* Did you write the Quaternion class, or did a 3rd party write it?
In either case, have you considered using Sun's Quaternion
implementation?
http://java.sun.com/products/java-media/3D/forDevelopers/J3D_1_3_API/......
No, because I want and need to do this myself to understand everything
about them.
I would trust Sun, but generally speaking I do not trust other
people's code - even if it supposedly works,
I still find that oftentimes they are sloppy in their style and not as
elegant as it can be. Besides, I've
trust Microsoft for years now and am getting tired of that
relationship. :)

No offense, but if their implementation of Quaternion works, and yours
doesn't, then maybe the level of elegance of their code is higher than the
bar you've set.

If you wish to learn Java programming, then it makes sense to write your
own versions of stuff, for the practice of it. But you'll have to one day
eventually learn to deal with other people's code, because software nowadays
is too complex for a person to implement alone. And then there's also the
principle of "don't reinvent the wheel".

- Oliver

Oliver,

I should have told you that I've been programming Java off and on for
several years and have been
a software engineer for about 16 years now. I think I know how to
deal with other people's code,
and most of the time, it's pretty lousy, so I'm fine with the bar I've
set, thank you very much. :)

Mike
 
C

Chris Uppal

Zerex71 said:
Thanks for looking over the code. As far as your suggestion, writing
it this way:

q3 = q1.add(q2)

is exactly something I don't want to do. To me, it just looks balky
and I'm not a fan of doing it that way.

I agree that it looks horrible for mathematical expressions. But then, I think

q3 = Quaternion.add(q1, q2)

looks horrible too (albeit not as bad). The only really acceptable syntax is

q3 = q1 + q2.

But that's not available in Java.

But there are a couple of advantages to using the standard method call syntax
(besides the fact that it /is/ standard). One is the rather trivial point that
it chains better than the external form.

q = q1.plus(q2).minus(q3);

rather than

q3 = Quaternion.add(Quaternion.add(q1, q2), q3);

The more important reason is that it is different semantically -- more
flexible, since it's a message send rather than a mere function call.

For instance, Alex Hunsley's suggestion in this thread, of making Quaternion be
an implementation of a general Field interface (or abstract base class) is only
possible if addition is left to the Field instances themselves (they decide how
they respond to plus()), rather than hardwiring the call by using a static
method.

Of course, I could be being too picky -- after
all, if I have a function thats
purpose is to add two numbers and return their result, isn't that good
enough, regardless of how
it looks?

I don't think so (that you're being too picky). For one thing, if you have
instincts which are telling you that you're not doing things "right", then the
thing to do is listen to them (and train them to work ever better), not to
ignore 'em. For a second thing, the "look" of the code is anything but a
triviality. Consider the following for a simple demonstration:

q = Quaternion.substract(q1, q2);

If that adds the two Quaternions together then you certainly have a "function
that [...] adds two numbers", but it is in no sense "good enough" -- in fact it
is completely evil !


I get neither experience from my current software engineering gig and
am none too happy about that,
so I code when I can.

Good luck. Have fun !

-- chris
 
L

Lew

Alex said:
Hashtable values = new Hashtable();
values.put("a", new Quaternion(1, 2, 3, 4.6));
values.put("b", new Quaternion(0, 0, -1, 3));
values.put("c", new Quaternion(-10.4, 0, 0, 4));

For my edification, why did you choose Hashtable over other Map implementations?

- Lew
 
O

Oliver Wong

Lew said:
For my edification, why did you choose Hashtable over other Map
implementations?

I'm guessing it's for the O(1) lookup, and 'cause order doesn't really
need to be preserved. These are names of variables used in the expression
that appears later: "(a*b - c^2)/2".

- Oliver
 
D

Daniel Pitts

I'm guessing it's for the O(1) lookup, and 'cause order doesn't really
need to be preserved. These are names of variables used in the expression
that appears later: "(a*b - c^2)/2".

- Oliver

Whats that have to do with Map vs Hashtable? If the question was "Why
aren't you using SortedMap", then your response makes sense. Ohwell.

Map<String, Quaternion> values = new HashMap<String, Quaternion>();

values.put("a", new Quaternion(1, 2, 3, 4.6));
values.put("b", new Quaternion(0, 0, -1, 3));
values.put("c", new Quaternion(-10.4, 0, 0, 4));
 
A

Alex Hunsley

Lew said:
For my edification, why did you choose Hashtable over other Map
implementations?

There wasn't a lot of thought put into the particular choice of which
map I used in the example! There may be more suitable choices. I did
start thinking about it when I wrote the post but realised I was
dallying too much when I had work to do, so put that particular reading
on hold and just sent my post.
lex
 
A

Alex Hunsley

Chris said:
But there are a couple of advantages to using the standard method call syntax
(besides the fact that it /is/ standard). One is the rather trivial point that
it chains better than the external form.

q = q1.plus(q2).minus(q3);

rather than

q3 = Quaternion.add(Quaternion.add(q1, q2), q3);

The more important reason is that it is different semantically -- more
flexible, since it's a message send rather than a mere function call.

For instance, Alex Hunsley's suggestion in this thread, of making Quaternion be
an implementation of a general Field interface (or abstract base class) is only
possible if addition is left to the Field instances themselves (they decide how
they respond to plus()), rather than hardwiring the call by using a static
method.

Surely the Field instances themselves could still handle the operations
statically though...
 
O

Oliver Wong

Daniel Pitts said:
Whats that have to do with Map vs Hashtable? If the question was "Why
aren't you using SortedMap", then your response makes sense. Ohwell.

Map<String, Quaternion> values = new HashMap<String, Quaternion>();

values.put("a", new Quaternion(1, 2, 3, 4.6));
values.put("b", new Quaternion(0, 0, -1, 3));
values.put("c", new Quaternion(-10.4, 0, 0, 4));

I was focusing on the keywords "other implementations" in "other Map
implementations". AFAIK, the other main Map implementation (TreeMap) doesn't
provide O(1) lookup, and the rests are for "special" situations (e.g.
EnumMap, WeakHashMap, ConcurrentHashMap, IdentityHashMap, etc.)

- Oliver
 
D

Daniel Pitts

I was focusing on the keywords "other implementations" in "other Map
implementations". AFAIK, the other main Map implementation (TreeMap) doesn't
provide O(1) lookup, and the rests are for "special" situations (e.g.
EnumMap, WeakHashMap, ConcurrentHashMap, IdentityHashMap, etc.)

- Oliver

You do realize there is a different between the Hashtable and HashMap
classes, right? I believe that is what Lew was asking about.
Hashtable is retained for backward compatibility only.
 
C

Chris Uppal

Alex said:
I've always found that idiom a little annoying in a purist sense,
although you're right in that it is a standard. I think that on first
look, when you're not used to this standard, you might expect an
instance method like q1.add(q2) to actually have an effect on the value
of q1 - but it doesn't (it just returns the result). And I know that
many people do trip up over this assumption, initially.
To me, Quaternion.add(q1, q2) is clearer - a result will be returned.

That, or something like it, is why I quietly changed the name of the instance
method from
add()
to
plus()
in my later example.

-- chris
 
C

Chris Uppal

Alex said:
Surely the Field instances themselves could still handle the operations
statically though...

I'm sorry, but I don't understand what you mean by that. Could you give an
example ?

-- chris
 
O

Oliver Wong

Daniel Pitts said:
You do realize there is a different between the Hashtable and HashMap
classes, right? I believe that is what Lew was asking about.
Hashtable is retained for backward compatibility only.

Oops. I missed that part.

- Oliver
 
C

Chris Uppal

Oliver said:
I was focusing on the keywords "other implementations" in "other Map
implementations". AFAIK, the other main Map implementation (TreeMap)
doesn't provide O(1) lookup, and the rests are for "special" situations
(e.g. EnumMap, WeakHashMap, ConcurrentHashMap, IdentityHashMap, etc.)

I think the issue was: why use the ancient, and largely superseded,
implementation of Map called Hashtable, instead of its (mostly) equivalent
replacement, HashMap ?

(Same slight irritation as seeing Vector used where ArrayList would be better.)

-- chris
 
A

Alex Hunsley

Chris said:
I think the issue was: why use the ancient, and largely superseded,
implementation of Map called Hashtable, instead of its (mostly) equivalent
replacement, HashMap ?

(Same slight irritation as seeing Vector used where ArrayList would be better.)

Actually, I was still in J2ME mode when I wrote that post - hence
Hashtable, which is available, whereas Hashmap ain't. (Similarly,
there's no ArrayList - you have to use Vector.)
 
L

Lew

Alex said:
Actually, I was still in J2ME mode when I wrote that post - hence
Hashtable, which is available, whereas Hashmap ain't. (Similarly,
there's no ArrayList - you have to use Vector.)

Aha!

- Lew
 
Z

Zerex71

In my continued question to implement some code, I ran across another
question.

I have a Vector class which is intended for use as a true, real vector
(mathematical), not the misnamed kind of "collection"
class that it usually it refers to. It is subclassed from the generic
Matrix class which contains the actual data members
(a 1,3 matrix storing three doubles in an array called, oddly enough,
"array"). Whenever I perform an operation that modifies
the values of Matrix.array, I want Vector to also have its attributes
(double x,y,z) to also be updated.

Here's the catch: Much of what I'm doing with the Vector right now is
static, so I'm only using the class to perform operations
for me, not so much to store content (although I will be using it for
that just as much very soon). My question is, if I invoke
Vector.operation() which returns another Vector, how does the
underlying array even get set? How do x,y, and z get updated if I
am using it statically?

Here's an example:

v_new = Vector.scale(v_old, k); // Standard scaling of a vector by a
length factor k
....
a = v_new.x(); // These are getter methods named identical to their
member variables
b = v_new.y();
c = v_new.z();

Also,

class Matrix {
double array[][];
....
}

class Vector extends Matrix {
double x; // Any time the underlying array[][] elements get
updated, these should be too
double y;
double z;
....
}

This implementation may be overkill, but I like the elegance of taking
this approach. Also,
the x,y,z and their corresponding getters are really for convenience -
"x" is a lot easier
to type than "array[0][0]". That sort of thing.

I'm sure I'm not explaining this fully but I think you get the idea.
Discuss!
 
L

Lew

A new topic deserves a new thread.
I have a Vector class which is intended for use as a true, real vector
(mathematical), not the misnamed kind of "collection"
class that it usually it refers to. It is subclassed from the generic
Matrix class which contains the actual data members
(a 1,3 matrix storing three doubles in an array called, oddly enough,
"array"). Whenever I perform an operation that modifies
the values of Matrix.array, I want Vector to also have its attributes
(double x,y,z) to also be updated.

Here's an example:

v_new = Vector.scale(v_old, k); // Standard scaling of a vector by a
length factor k
...
a = v_new.x(); // These are getter methods named identical to their
member variables
b = v_new.y();
c = v_new.z();

Also,

class Matrix {
double array[][];
...
}

class Vector extends Matrix {
double x; // Any time the underlying array[][] elements get
updated, these should be too
double y;
double z;
...
}

This implementation may be overkill, but I like the elegance of taking
this approach. Also,
the x,y,z and their corresponding getters are really for convenience -
"x" is a lot easier
to type than "array[0][0]". That sort of thing.

Don't have instance variables for x, y and z. Define the methods in terms of
the underlying, inherited array.

public double x()
{
return array [0] [0];
}

- Lew
 
Z

Zerex71

A new topic deserves a new thread.


I have a Vector class which is intended for use as a true, real vector
(mathematical), not the misnamed kind of "collection"
class that it usually it refers to. It is subclassed from the generic
Matrix class which contains the actual data members
(a 1,3 matrix storing three doubles in an array called, oddly enough,
"array"). Whenever I perform an operation that modifies
the values of Matrix.array, I want Vector to also have its attributes
(double x,y,z) to also be updated.
Here's an example:
v_new = Vector.scale(v_old, k); // Standard scaling of a vector by a
length factor k
...
a = v_new.x(); // These are getter methods named identical to their
member variables
b = v_new.y();
c = v_new.z();

class Matrix {
double array[][];
...
}
class Vector extends Matrix {
double x; // Any time the underlying array[][] elements get
updated, these should be too
double y;
double z;
...
}
This implementation may be overkill, but I like the elegance of taking
this approach. Also,
the x,y,z and their corresponding getters are really for convenience -
"x" is a lot easier
to type than "array[0][0]". That sort of thing.

Don't have instance variables for x, y and z. Define the methods in terms of
the underlying, inherited array.

public double x()
{
return array [0] [0];
}

- Lew

Your last suggestion I can live with. I just wanted to use the x, y,
and z names as ways to reference.
That still leaves the question of how the array gets updated if I am
using the class in a static fashion
i.e. not setting its individual members to particular values. As to
the former suggestion, it's a continuation
of an earlier topic, so sorry.
 
L

Lew

Lew said:
Don't have instance variables for x, y and z. Define the methods in terms of
the underlying, inherited array.

public double x()
{
return array [0] [0];
}
Your last suggestion I can live with. I just wanted to use the x, y,
and z names as ways to reference.
That still leaves the question of how the array gets updated if I am
using the class in a static fashion
i.e. not setting its individual members to particular values.

Use an appropriate setBlah( double val ) method.

Or perhaps setBlah( double val, int row, int col ).

This business of hiding all attributes behind accessor methods is quite
powerful, at the cost of verbosity. A method pair "setX()" and "getX()" need
never reference an actual instance variable "x" within the black box. They
only need to present to API clients the view of "x" as an attribute.

Don't use static members unless you really intend the value to be what it is
for the entire class. If your analytical model says, "I can have two Vectors,
call them 'va' and 'vb', and they can contain separate values, and not be
equal in value to each other", then the model requires that the "values" for
Vectors be instance-level.

While you're at it, you will want to override the Object methods equals() and
hashCode(), in a consistent manner.

You also face the decision of whether to make Matrix instances immutable, in
effect "read-only" after construction. There are distinct benefits to doing
so, but it complicates objects that support calculations.

Joshua Bloch covers these overrides and immutability admirably in his book
/Effective Java/, and there are many articles on these topics. GIYF. So are
IBM DeveloperWorks and Sun's Java sites.

P.S., in UMLish diagrams and class design documentation, I model accessor and
mutator methods as attributes, not methods. At times some of my colleagues
want to change the design docs to match the physical implementation as
methods. This is, of course, working the wrong way around.

- Lew
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top