

Java Gets Templates 121
lastberserker writes "Call them all you want - generics, parametrized types, thingamagic mumbojumbo - but (tada!) Java gets templates in 1.5 release. Nice landing after 5+ years of dancing around a bush. Competition is good, pardon my pun."
OMG templates totally rule! (Score:2)
Oh, and I was thinking of another kind of templates (web pages/content/presentation) when I read the title, but of course we have waay too many of those in Java already.
So, what else is still missing from the language? It seems almost ready to go mainstream.
Re:OMG templates totally rule! (Score:5, Informative)
BTW. generics are old news. The prototype compiler and the proposal have been available for at least a year. On the javalobby there's a link to some additional language extensions: http://www.javalobby.org/thread.jsp?forum=61&thre
Re:OMG templates totally rule! (Score:1)
Hmm, I think you get it more than lightspawn does, but when you said "generics are old news" I was expecting that you were about to point out that templates (as they exist in C++, Modula-3 ('generics'), and numerous other languages) are basically a kludge to work around limitations in the object model.
The Beta programming language [daimi.au.dk] has a much better object model than Java/C++, which completely obviates the need for templates while still providing type-safety; basically, it lets you override 'data members' as well as 'function members' of your classes when subclassing.
Of course, Beta is a bit hard to come to grips with if you first encountered the idea of an object-oriented language in the context of C++ or Java. Still, a little mind-bending can be good for one's perspective...
Re:OMG templates totally rule! (Score:2, Insightful)
-- Eldergeek
It's a treat to beat your feet in the missedthepointand mod
Re:OMG templates totally rule! (Score:2)
I agree that probably Java's generics are a bit of a compromise between the Java object model, generics security and type safety. Arguably, C++ is more powerfull but less safe in that respect. Probably Beta does a better job at implementing generics. However, generics are not the solution to all problems. Essentially separation of concerns is not possible for all problem dimensions (which is what both OO and generics try to achieve).
Re:OMG templates totally rule! (Score:1)
Given how templates exist in C++, all it takes away is just few casts. Which as in comparison to templates are naturally type safe, because with templates you can only handle a certain type in the templated object, thus if in such case you use type casting, where's the problem?
I am a C++ programmer, so don't flame me for that.
But seriously all it reduces is few type casts.
Re:OMG templates totally rule! (Score:2)
Re:OMG templates totally rule! (Score:1)
Re:OMG templates totally rule! (Score:1)
Re:OMG templates totally rule! (Score:3, Informative)
The Java equivalent would return an Object and take two Objects as parameters. All the type safety you work so hard to preserve is lost, and at run-time you're taking a performance hit every time this is called for a myriad of reasons.
Re:OMG templates totally rule! (Score:3, Informative)
The Java equivalent would return an Object and take two Objects as parameters.
No, the java equivalent would use an interface, probably called "comparable" or somesuch.
Re:OMG templates totally rule! (Score:1)
But that just my own opinion.
Re:OMG templates totally rule! (Score:1, Redundant)
Object Max(Object x, Objecty) {
if(x > y) return x else y;
}
or some such - my java is rusty. perhaps you need to standardise on a function, say, x.biggerthan(y) and ensure it is transitive, reflexive, commutive etc...
Re:OMG templates totally rule! (Score:3, Flamebait)
Re:OMG templates totally rule! (Score:4, Funny)
Until it has that it is obviously not complete!
Re:OMG templates totally rule! (Score:1)
As for the rest, it would be nice, but we can continue surviving without these until 1.6 or so ;-)
Re:OMG templates totally rule! (Score:2)
BTW, even in Java people use poor man's HOFs, namely in form of anonymous inner classes. Hardly elegant, IMHO.
The C preprocessor is indeed external to the language, but it doesn't have to be that way. Think Lisp macros, or CamlP4 for Objective Caml, where you deal with language elements structurally, not just modify text.Re:OMG templates totally rule! (Score:1)
Missing from the language... (Score:3, Insightful)
Well, I don't know about most Java programmers, but the missing features that constantly bug me are:
- Higher-order functions (Seriously, you can't live in a language that doesn't have this once you get used to programming with them!)
- Algebraic Types and Pattern Matching (Vital for manipulating syntax trees, like in a compiler)
- Tuples
- Getting rid of 'null' (This is possible, in fact, easy, and would make the language much cleaner, less error prone, and even more efficient)
- Uniform typing discipline (ie, int vs. Integer
- Parameterized Modules (a la SML's functors)
There are also some bugs in the language itself, though those wouldn't really bother me day-to-day.
- Arrays are covariant, leading to class tag checks on every array write (in the general case)
- The description of binary compatibility is broken (It can lead to situations where recompliation of the class files either leads to a different program, or to a failure to compile!)
-
A language that makes some of these strides is called Nice [sourceforge.net] , though I've never used it.
Re:Missing from the language... (Score:1)
Thanks.
The problem with null (Score:2)
You might have something built in to the language like this, like writing "Integer?" as the class name (the language Popcorn does this), you might also just have a powerful enough language that it can be coded up easily (SML has this with its polymorphic 'option' type).
With the old null, you might write this:
Integer x = something();
if (x != null) {
} else {
}
Note that if you pass x to another function, that function probably needs to check to see if x is null, too. Similarly, the bytecode interpreter needs to check for null whenever you do a method invocation on x. Without null, you might write (I am just making up the syntax; you might want to see how Nice does it):
Integer? x = something();
switch (x) {
null:
Integer(y):
}
The important thing here is that we've statically captured the fact that we've done a null check (y would have type 'Integer', not type 'Integer?'). Now, the byte code interpreter never needs to check y to see if it's null (efficiency gain), the programmer is never allowed to use a value unless he's checked that it's null (program robustness), the potential for a function to return null is reflected in its type (modularity), and the programmer has to insert fewer checks, because once it's an Integer, it is not necessary (and doesn't make sense!) to check for nullness (saves typing).
In my own Java programming, and experience with using other folks' Java programs, the Null Pointer Exception is much more common than the Class Cast Exception. However, in my experience with Object Oriented Programmers, the love of "null" runs deep, so it might be a harder sell than generics!
Re:OMG templates totally rule! (Score:1)
If that is what you think of when you hear "templates" in reference to programming languages, perhaps you need to become more familiar with the world of Computer Science (not computer programming -- there is a difference). Anyway, that sentence gives the impression that you don't spend enough time deep in code to make any experienced comments about language features.
You know, I've never felt a need for templates.
This is either flamebait, you don't know what the real principles of system design are (see the Computer Science comment above), or you don't have enough experience to be speaking. Perhaps a combination of the three.
You're the one controlling what data goes into which data structure, so as long as you're not confused (and not forced to work with people who are) templates aren't necessary.
Parameterized containers are just one use of templates, and obviously you haven't found the others. Programmers with a lot of experience are usually very excited when they learn about templates, because they can immediately see where they would be really useful. If you can't, then you need to do more reading than speaking (insert sagely counsel here ending with "young padawan"). A function needs to be written twice, once for 8-bit characters and once for 16-bit characters. Templates make it possible to write (and, more importantly, maintain) just one version of the function that handles both situations. And it will also nicely handle the situation of 32-bit characters just fine if that situation ever arises.
Even in the case of simple parameterized containers, templates do a lot more than you give credit for. First, it isn't always YOU that puts stuff in the container. Did you know that some programs aren't written by just one person? Yes, really! So sometimes somebody else misunderstands what goes into your nice generic vector named "nuts". It compiles ok, and works most of the time, but once in a while an exception now pops up. Hey, how did this walnut get into my peanut vector?
Second, when extracting items from the vector, there is no need to cast the type. And remember that casting actually has a runtime cost -- the system has to verify the type.
It [the Java language] seems almost ready to go mainstream.
Alright, if that isn't flamebait, I don't know what is.
Operator Overloading? (Score:3, Interesting)
Re:Operator Overloading? (Score:2, Interesting)
Java ain't complete 'till C# compiles on it?
(if Java is gonna have weird cool features added, I'd like to vote for what I read in the Eiffel doc the other day: design by contract, with pre and post conditions and class invariants. )
Nooooooo (Score:3, Insightful)
<irony> 1+1=3 for large enough values of 1 is the most I can concede in operator deviant behaviour. </irony>
Re:Nooooooo (Score:2)
The meaning can be the same, or different - it depends on the body of the function, not its name. Just like, say, toString() can do what you expect it to - or something else entirely. The language should not be expected to prevent you from defining functions named toString() just because they don't perform the function you think they should. Why should it be any different with operators?
Re:Nooooooo (Score:5, Insightful)
With that short a definition, the operator's meaning must be inferred by the reader's culture. + is the arithmetic sum operator. We know what it does after working with it for years.
Methods, on the other hand, can have extremely verbose names. That is one of the good things on the Java coding guidelines. Names are verbose. There's no strcmp. There's String.compareTo. If the compare is case insensitive, there's String.compareToIgnoreCase.
Objectively, you are right. There's no guarantee a function performs what its name implies. However, if a function's name is incorrect, I can smack the developer on the head. If an operator's name is incorrect, the developer may have done it right, since having an operator named multiplyTransposeAndNormalize is awkward. It's the whole concept of operator overloading that is wrong.
AAAAAAAAArgh -- missing the point sooo badly (Score:5, Interesting)
Sorry, but I'm going to rant now, because every time I see this ill-informed argument it really annoys me.
Operator overloading is a fact of life when you are working with generics. Suppose I want to write a generalised summation method, which adds up all the elements in a list, whether those are int, float, SomeComplexNumberType or whatever. Question: what well-known and easily understood notation would make sense to use when writing this method? Should I write another method called add that has several versions, for each type I'd like to add up? Or maybe it should be addTo? After all, by your own argument, verbose and descriptive names are the way forward. But what if someone else provides a fixed-point type with a method called sum instead? Or maybe a static method taking two fixed-point values called sumOf? Do you see my point here? If everyone uses + to mean +, then writing such code is easy. If everyone uses different notation, which is forced if you don't allow operator overloading, then what you get is unmaintainable crap that cannot take advantage of generics in many of the most useful ways.
Java already has operator overloading anyway. You have + to concatenate strings. You have a conversion operator called toString. You have / that divides real numbers, but takes the integer part of the result for integral types. The only difference between these and what you have in a language like C++ is that in Java, you can only take advantage of this concept where the Java designers want you to, whereas in C++, you can write your own types at full strength as well.
Yes, operator overloading can be abused. So can method naming (and no, you can't smack the developer on the head, if he happens to work on the other side of the world and you're stuck using his library). But op overloading is more than mere syntactic sugar, where generic programming is involved. There are accepted standards for how we write certain concepts such as addition or strict ordering, and operator overloading is necessary to allow user-defined types to meet those standards, and thus to allow well-written generic code to take advantage of parameterised types and such to best effect. Without it, you've got a fabulous canvas, yet nothing but coarse paintbrushes to draw with.
Alas, as is so often the case, I fear the Java community has been too quick to think it understands, and to go for the buzzword feature without investigating the supports deeply enough. Parameterised types are a good start, and I'm glad to see them included, but I suspect that with experience, there'll be some serious enhancements in a couple of revisions' time...
Re:AAAAAAAAArgh -- missing the point sooo badly (Score:5, Insightful)
I don't necessarily disagree with everything you're saying here, but a few things drew my attention....
You have a conversion operator called toString
Um, no. You have Object.toString() which is a method, not an operator.
There are accepted standards for how we write certain concepts such as addition or strict ordering, and operator overloading is necessary to allow user-defined types to meet those standards...
It sounds like you're talking about why operator overloading is necessary for C. For one, "user-defined types" don't exist in Java. Second, I don't agree with what you're saying. What about Lisp? Do you think that Lisp is a poor language because you don't add two numbers by saying 1 + 2? Lisp breaks your "accepted standards for how we write... addition".
Re:AAAAAAAAArgh -- missing the point sooo badly (Score:2)
I think he means "classes". Why should '+' work for the java string class, but not for a user defined string ?
Second, I don't agree with what you're saying. What about Lisp? Do you think that Lisp is a poor language because you don't add two numbers by saying 1 + 2?
There are accepted standards for what '+' means. Even in LISP. The fact that the lisp programmer writes (+ x y) instead of x + y is not relevant -- the point is that it makes sense to have x+y or (X x y) mean the same thing ("add these things together) for user-defined types (like big numbers, high precision floating point numbers, quaternions, finite abelian groups, matrices) as it does for built-in types.
Um, yes. :-) (Score:2)
Perhaps my terminology isn't the norm in the Java world, but nonetheless, what you have is exactly the same as a conversion operator in other languages. It is a means of implicitly converting between types. Except that in Java, you can only set that up for conversion to a String implicitly. (Don't even get me started on why all classes should have to provide this method in the first place, or on the common root class flamefest.)
Really? What's a class, then?
Lisp has an accepted standard of its own: (+ 1 2) is the sum of the numbers 1 and 2. The point is not a universal notation, but a consistent notation within the language, which allows you to write a generic method once that can work with any suitable type without further modification.
Your example is particularly ironic because Lisp's S-expressions are a prime example of exactly the sort of uniform syntax I'm advocating here.
Re:Um, yes. :-) (Score:1)
Seems to me that the whole crux of what you don't like about Java (at least as relates to this subject...) is that there is a fairly marked distinction between primitive types and classes. They behave differently. They are used differently. Yes, Strings do use the + operator and there is implicit toString() calling, which ar an exceptions (side note: I have no idea what you mean when you say "Except that in Java, you can only set that up for conversion to a String implicitly"). If you're that much of a "purist" that this is a problem for you, then maybe only Lisp is uniform enough for you.
But really, as others have pointed out, what does it mean to add a primitive to an object (of a perhaps arbitrary class) or two different objects? Why is it really so wrong that you have to define in a method what happens when you add them?
Let's just compare them, and see... (Score:2)
My objection isn't just that primitive types and UDTs work differently, although that is a fundamental cock-up that should long since have been fixed. My main objection is that we already have a sensible way to represent these concepts, and it's absurd to go around reinventing the wheel, and in a somewhat arbitrary way at that, rather than going with the obvious.
Is it really wrong that a multiply-and-add operation on two matrices be written as M = A * B + C? Or that a new date should be calculated with seasonEnd = seasonBegin + seasonLength? Why is it in any way better to write something like:
or any of the zillions of other possible permutations? Do you honestly feel that this is less subject to abuse, or less error-prone?
And why shouldn't my parameterised tree container, and the algorithms that operate over it, be able to work with int and float data, as well as BigNumber and FixedPoint values? Why should I have to write it all twice (at least)?
Operator overloading is much cleaner, reduces the programming effort required to develop parameterised data structures by a factor of at least two, and consequently reduces error rates. The only point I've seen against it that is true is that there is scope for misleading operator overloads to be provided. It isn't hard to see the conclusion, if only you sit down and look at it objectively.
Oh, and the implicit conversion thing relates to the fact that I can convert an object into a string just by context ("some " + myObject + " thing") but I can't implicitly convert to an int for analogous summation purposes, say.
Re:AAAAAAAAArgh -- missing the point sooo badly (Score:1)
Re:AAAAAAAAArgh -- missing the point sooo badly (Score:3, Insightful)
In Java, operators already only apply to primitives anyway, with the exception of the + operator, and then only when in a string context (ok ok, there is 'instanceof' and 'new'...i'm not sure if these can be meaningully considered "operators" as they are reserved for very specific uses). Collections also only apply to objects. It already doesn't make sense to be able to perform certain operations on arbitrary objects. E.g., what does the addition operation do with operands of Bicycle type and the Color orange? If you are going to use generics for collections, you are already going to declare them to use some homogenous base class. In your case it would be something like Addable, which would have an add() method or whatever. Or perhaps just Number, from which you get primitive values, and add them with the primitive + operator. At some point you have to draw the line in defining things. Performing arbitrary operations on arbitrary objects at best makes no sense, and at worse can be very very dangerous.
Re:AAAAAAAAArgh -- missing the point sooo badly (Score:2)
With respect, I think you miss the point as well. The fact that Java treats primitive types differently from those derived from Object is already a serious thorn in the side of many a programmer. This sort of generic feature could provide a systematic, uniform way of dealing with such types, banishing the need to use bastardisations like Integer to a much smaller range of applications. This, IMHO, is a Good Thing.
You're quite right, of course, that it doesn't make sense to try to add an apple and the colour purple. What you're ignoring is that you simply wouldn't provide an addition operator taking a Bicycle and an Orange, and thus trying to do add them with a generic function could and should result in a compile-time error, or at least a run-time error if you're relying on late binding. There is no problem here; at worst it's the same as what you've got if you do the same thing in non-generic code now.
Re:AAAAAAAAArgh -- missing the point sooo badly (Score:1)
I believe Java generics don't support primitive types, only classes and interfaces.
Should I write another method called add that has several versions, for each type I'd like to add up? Or maybe it should be addTo?
The problem you pose is real: We should have a standard way of adding to instances of a certain type. However, IMHO the best solution isn't to add operator overloading, but rather to standardize an addition interface:
And of course you can also make it generic to avoid downcasts..Re:AAAAAAAAArgh -- missing the point sooo badly (Score:2)
Oh, dear. I read about that when the proposals first flew around a while back, but I confess I thought they'd changed it, and didn't really check in detail this time.
That's a shame, because now one of the few really good things that was going to come of this hasn't.
We already have one of those: it's called the + operator. :-)
But seriously, your approach is fundamentally flawed in at least one totally unnecessary way: it requires a different interface to be implemented for each relevant method, so a numeric class might well have to implement more than a dozen interfaces just to do the basics (and still wouldn't be compatible with primitive types, unless you're going to provide that interface for them as well). Presumably your parameterised functions or types are also going to list all the interfaces they require of each parameter type explicitly as well?
But Comparable has always been a bit of a dark hat in a room full of white suits. It's there exactly because the need I'm talking about exists, but for some reason people I've never fathomed Java people don't seem to like operator overloading.
The question is, at what point does this break down? Do you provide interfaces for LessThanComparable, StrictlyLessThanComparable, EqualityComparable, InequalityComparable, GreaterThanComparable and StrictlyGreaterThanComparable, to correspond to the various equality and inequality operators? (Do you make the primitives provide them as well?) Do you try for more abstract concepts, such as Ordered or StrictlyOrdered? The latter is probably better style, but then you lose an element of precision that might be important when working with arbitrary types. Perhaps you start with an interface for each method, and then create more abstract, compound interfaces derived from them? But now, my poor little class that just wants to compare two int members for an ordering, is supporting multiple layers of interfaces, several at a time, and providing an artificial method, just so I can sort it?
Thanks, but I'll take operator overloading and proper generics any day.
And by the way: I'll think about admitting that operator overloading is mere syntactic sugar just as soon as you show me a class that works like a function, so I can pass it in to a generic algorithm. :-)
Yeeeeeeeees (Score:1, Insightful)
But sometimes the terse name is the right one to use. The standard examples come from maths programming. If you have a Complex number class, then it is far more natural to write
Complex c1;
Int i;
Complex c2 = c1 + i;
Rather than
Complex c2 = c1;
c2.addInt(i);
Of course a method is usually the best place to put functionality. But not always Blitz [oonumerics.org] is a great maths library using templates and operator overloading when necessary to produce a very powerful and usable system.
Other examples are the iostream library and STL in C++.
The ability to overload the <operator allows the STL to use primitive types and user defined types in the same algorithms.
Re:Nooooooo (Score:2)
No, this is write-only software.
a = BigInt(xyz);
b = BigInt(pdq);
a.add(b.div(3))
Yesssss, for mathematical types (Score:2)
Vector w=x+y+z;
Otherwise, the math gets _badly_ obfuscated and buried in minutia. I have yet to use a language that allowed it. (Yes, this is a pet peeve.)
And I don't buy that it won't be clear what "+" means in each case. It means the addition operation that makes mathematical sense given the operands. If that isn't clear to you, you aren't going to get the code no matter how it's written.
Example time. The addition code is written for binary (2 argument) addition, because you shouldn't have to write more than. Assume addition code also allocates the memory or invokes the constructor for the result, because it gets *really* ugly if it doesn't.
C: You have to use a name instead of "+", and you have to manage the memory. I wrote a few thousand of lines of this stuff as a grad student.
double *temp = vectoradd(x,y);
double *w = vectoradd(temp,z);
free(temp);
C++: You can use "+", but you still have to manage the memory. [It's possible to do better if you overload "=" to do reference counting. But if you don't like overloading "+", you really won't like that.]
Vector temp = x+y;
Vector w = temp+z;
~temp();
Java: You don't have to manage the memory, but you are back to using names:
Vector w = x.add(y).add(z);
If these examples don't seem very messy, see what (a*x*x+b*x+c)/(d*x*x+e*x+f) turns into if you change the variables from doubles to some object type -- say representing complex numbers. And remember that that's pretty simple as math expressions go.
Here's what I propose: don't let the programmer overload "+" arbitrarily. But for classes which implement certain kinds of mathematical entities, have a set of methods they must implement with the types that make mathematical sense. E.g. if class foo claims to be a vector, it must implement
public foo add(foo, foo)
public foo scalarMultiply(double, foo)
public foo scalarMultiply(foo, double)
Then overload the standard arithmetic operators with these methods. It should be possible to make it work well for mathematical objects, but unpleasant for anyone who wants to tries to cheat the system.
But you can't guess what other types it would help (Score:2)
And how, exactly, do you propose to work out who is "cheating the system" and whose use is quite legitimate? Is the use of + to concatenate strings acceptable to you? What about other string-like classes? How about for adding date/time and time period classes?
At the end of the day, you can never anticipate every use to which such a feature could usefully be put. You have two choices: try, and provide something that is sometimes useful but usually frustrating, or leave the choice to the informed developer, and let them do what they will with it. The fact that C++ is still here is testament to the fact that the second approach works. I can't think of a single language that tries to restrict the programmer this way that has lasted more than a short period.
Re:But you can't guess what other types it would h (Score:2)
But you're basically right. I don't know how many mathematical types -- or properties -- I would want to add. It would probably be a few dozen, and undoubtedly more in the second release.
I don't want my languages telling me what to do any more than you do. But that's not where I'm going. I need both overloading and automated memory management, and I need them in a compiled general purpose OO language. But I only need overloading in a specific context where it really makes sense. I'd be quite happy with a design-by-contract setup which requires that the class fulfill (within roundoff error) the appropriate mathematical definition. E.g. to be a semigroup, you have to have the operator be associative. That is, (a+b)+c == a+(b+c).
And that shouldn't trigger the (legitimate, IMO) complaints that overloading-heavy code is write-only.
Re:But you can't guess what other types it would h (Score:2)
I think we're on the same wavelength, but just a couple of points are worth mentioning...
Firstly, it's almost invariably not true that (a+b)+c == a+(b+c) from a numerical analysis point of view. The problems of limited precision render such mathematical niceties, well, niceties. While I appreciate that it would be nice to program in a higher level language where such mathematical contracts were used, none of those under discussion around here will ever qualify.
As for overloading-heavy code being write-only, I couldn't disagree more. Code where operators are overloaded usefully (viz. typical mathematical types, string concatenation, etc.) is far more readable than the equivalent with longhand methods being used all over the place, particularly in a language such as Java that has no free functions. The only time such code becomes write-only is when the operators are overloaded in a misleading way (for example, having unexpected side-effects) and that's no different to the effect of choosing a bad name for any other function, or variable, or type.
OK, we're almost in agreement (Score:2)
I don't have a much experience reading other people's code with overloaded operators. But I think overloading would help clarity if, and only if, the overloaded function is enough like the builtin version of the operator. At a minimum, the semantics need to be analogous and the presence or absense of side-effects needs to be the same. Overloading "=" to implement reference counting doesn't qualify in my book. (This is closer to what you just said than to what I initially proposed.)
After all, in many languages the builtins are essentially overloaded -- int+int isn't the same thing as double+double.
Re:Yesssss, for mathematical types (Score:1)
Vector temp = x+y;
Vector w = temp+z;
~temp();
Not only is that invalid C++ code, but you seem to be complaining about a non-existant problem. Your class should look something like this:
#include <stddef.h>
#include <assert.h>
#include <algorithm>
#include <iostream>
class Vector {
double * d_; size_t nElems_;
public:
typedef size_t size_type;
Vector( size_type n ) : d_(new double[n]), nElems_(n)
{ std::fill_n( d_, n, 0.0 ); }
Vector( const Vector& v ) : d_(new double[v.nElems_]), nElems_(v.nElems_)
{ std::copy( v.d_+0, v.d_+nElems_, d_ ); }
double& operator[]( size_type i )
{ assert( i < nElems_ ); return d_[i]; }
Vector& operator=( const Vector& v ) {
if( v.nElems_ > nElems_ ) {
double * tmp = new double[v.nElems_]; delete[] d_; d_ = tmp;
}
nElems_ = v.nElems_;
std::copy( v.d_+0, v.d_+nElems_, d_ );
return *this;
}
Vector& operator+=( const Vector& v ) {
assert( v.nElems_ == nElems_ );
for( size_type i = 0; i < nElems_; ++i ) d_[i] += v.d_[i];
return *this;
}
size_type size() const { return nElems_; }
~Vector() { delete[] d_; }
};
Vector operator+( const Vector& lhs, const Vector& rhs )
{ Vector tmp(lhs); tmp += rhs; return tmp; }
int main() {
Vector a(10); Vector::size_type i;
for ( i = 0; i < a.size(); ++i ) a[i] = i;
Vector a2 = a + a;
for ( i = 0; i < a2.size(); ++i ) {
if ( a2[i] != a[i] + a[i] )
std::cerr "a2 is not a + a" std::endl;
}
}
I stand corrected (Score:2)
It's been a while, but I believe I was manipulating pointers to objects to avoid all copying. The application was computationally intensive, but it was probably silly of me anyway.
My C++ experience isn't extensive, and the implementation wasn't exactly modern.
Why is "plus " more readable than "+"? (Score:2)
Re:Why is "plus " more readable than "+"? (Score:2)
With +, you can't verbosely specify the behaviour and implement all three cases -- see my other post in the thread. With the method notation, you can have:
Comment removed (Score:3, Insightful)
Re:How sad (Score:2)
(so, for example, I could declare a SortedList type, where only types that implement Comparable can be used)
would probably do that for youDisclaimer: I didn't actually check the spec, but int the page of the article there is nothing that indicates that is has to be a class and not an interface or abstract class
Re:How sad (Score:3, Informative)
Damn I hate replying to myself
It seems I may have misunderstood the parent post. Reading through it again I believe he meant something like
which it seems the specification doesn't support, and it should have. (to be really useful)
Re:How sad (Score:1)
Don't get me wrong here, I'm a C++ (and Java) programmer myself, and I do use templates every so often, but seriously that's not the thing you need templates for. If you already have a common interface for the storable items that provides you the stuff you need you really don't need the template at all.
I've seen all sorts of people write all sorts of heavily templated code over the years and I must say that the need for them (besides some heavy trickery and ioccc uses) there's been little accomplished that couldn't have been done equally well using other means.
I never understood why was it so much easier to use templates and rely on the fact that the class has said compareTo method than it is to then declare that your class implements interface Comparable for example.
Besides implementing templates for java all in all escapes me. Although it may strip away few casts, but I wonder wether that really makes things better.
Re:How sad (Score:2)
One of the major plus points of templates is precisely that they don't require you to implement a particular interface by name. Thus they can adapt to any types provided by other parties that provide the necessary interface functions without explicitly saying that they derive from some known base class.
And yes, stripping away the casts is better. It reduces a major class of bugs from run-time to compile-time, and that is a Good Thing.
Re:How sad (Score:2)
In Java, if you specify that any class T can be used, you can call only methods declared in Object on variables of type T. If you want to call other methods, you must constrain the type to a subtype of Object.
Re:How sad (Score:2)
I did mention that myself, if you check. :-)
And this is where the approach now taken in Java is seriously inferior: there goes your type safety. How, pray tell, are you going to mandate that some third party library developer must implement a suitable interface in any class they provide, such that you can write generic methods to work with a whole family of types that support the interfaces you need, without knowing in advance what they are? Must they implement a single-method interface for every method in their class, and must you specify explicitly which methods' interfaces are required for your generic function? I don't think you've thought this through far enough.
Re:How sad (Score:2)
Why do you say "there goes your type safety"? Can you explain in detail why Java generics are not type safe?
I also don't follow the vague example you give about the third party developer. I can't recall any situation I encountered like that when using C++ templates. Can you give a more specific example?
Clearer answers, I hope :o) (Score:2)
It's not that they are necessarily not type-safe, not in the way that the current containers are because you have to perform a potentially wrong downcast to use them.
However, suppose I develop the world's greatest sorting algorithm, and I want to write a generic implementation for it to sort arbitrary sequence containers of arbitrary types. There are inevitably certain minimal requirements: I must be able to traverse my container in a suitable way for my algorithm to work, the types must support a suitable ordering relation, and so on.
As I understand it, several people in this thread are advocating the use of interfaces to ensure that only suitable types get passed to my sorting algorithm, thus ensuring type safety. The problem with that is what happens when someone comes along with a new container or sortable type that provides the necessary methods, but doesn't explicitly use that interface. Now my "generic" sorting algorithm can't be used, purely because of a naming issue. (I realise there are certain standard interfaces defined for things like comparison in Java, but obviously for types and algorithms in general that won't be the case.)
The requirement to implement interfaces explicitly is simply an unnecessary bar to the use of generics. In other languages, from C++ to SML, you can achieve similar effects without ever explicitly naming your interface. Instead, the algorithm simply fails to compile if it's used with types that don't match the way the algorithm uses them. Added to the presence of operator overloading, which standardises many fundamental arithmetic and logical operations from the start, writing generic algorithms that really are quite general is significantly easier.
Further, the concept of an interface as defined in languages like Java is inadequate to enforce useful constraints in practice anyway. The suggestion has been made, and refuted, many times in the C++ world, and alternative approaches to document and enforce constraints within template code have been developed instead.
The only alternative that I see as Java's generics stand today is to define all your generic algorithms to work with any Object, and go back to downcasting, but then you might as well never have bothered with generics in the first place.
Thus your two alternatives are either an interface-based system, which is type-safe but unnecessarily restrictive and less efficient, or to use generics only for type-safe containers and to write your generic algorithms in terms of Objects, which leaves open type safety loopholes.
Ultimately, implementing generic algorithms will always suffer because one man's search method is another man's find. It is helpful to offer methods of standard names to make generalising code easier, but clearly you can't have a standard interface for everything in a general purpose library that may be put to any use. I advocate the use of operator overloading, because the sorts of calculations performed by built-in operators tend to be useful in a wide variety of contexts. Beyond that, if your generics only deal with the methods that are actually presented, whether or not they're explicitly identified by a formal interface, at least you keep the range of application as wide as possible. If you need to go farther still, you're into the land of intermediate classes (such as the iterators in C++'s standard library) to standardise an interface by force. In that case, you can always implement a named interface there, but of course there's an inherent performance hit in doing so, and you really want such intermediate classes to be so lightweight that you don't even realise they're there under normal use.
Re:How sad (Score:2)
You are right, there is no absolute need for templates. But if they are going to implement them they should do it right, and that mean beeing able to force one or more interface(s) and/or a base class as the template type. After all the reason was stronger type safety
e.g. for a collection class you could just as easily just use that interface or base class as the parameter, and document that all object in the collection should be the same class
It's basically an extra bit of syntax to generate compile-time errors instead of run-time errors, letting stupid programmers know earlier:)
Re:How sad (Score:2)
To answer your question, if you don't mind a C++ focus, may I suggest that you read Andrei Alexandrescu's "Modern C++ Design", Addison-Wesley, Boston, Mass., 2001, ISBN 0-201-70431-5. Among other things, it offers a way of facilitationg the explicit coding of design pattern implementations.
Re:How sad (Score:4, Informative)
class MySortedList<Element implements Comparable> {
void insert(Element e) {
int i = e.compareTo(another_element);
}
}
Re:Not really the point. (Score:4, Informative)
Although I agree with you, I must say that "understanding object orientation" amongst programmers is little like "understanding humour" amongst ordinary people. Everybody think they do.
Any language (that I know of, and that is quite a bunch) can be used to write "proper OO code" aswell as plain-old imperative programming.
I think Alan Cox put it well when he said "object orientation is a state of mind". Linux kernel is really object oriented on many many levels.
Re:Not really the point. (Score:1)
Yep, that is so true. There is also the question of "proper editor"...
Besides such a huge amount of programming indifferences are really about coding style and other irrational issues. Even some of the OO concepts depend on one's liking.
Java does not make procedural programming very simple. I still can't get:
print("hello world");
in Java without dotted thingies hanging from its ass or funky interface declarations for every fricken class that uses it.
Nah, it's just as easy. But nonetheless my point was more along the lines "no matter how we rant about certain language features, the bottom line will always be 'good programmers write good code and crappy ones will crap on their terminals'". I know it sounds awfully trivial, but somehow people do tend to forget. Especially during IT boom few years back every god damn company hired anybody how knew how to spell computer. I've heard of people claiming to know java, but then when allowed ask questions have said "just one, what are all those dots and parentheses for?". (and that's a true story)
I think Sun errored in its OOP-only push. Even many OO fans agree that procedural is sometimes the best approach for *some* things.
I couldn't agree more. We've been writing an OS from scratch in C++ that will run Java bytecode and it's not just the little things that break out of the OO style. There are numerous things in a kernel that doesn't make sense in OO, but also numerous things that naturally go beautyfully that way. I can't help constantly thinking why we're bothering with C++ at all, although that's really my language of choice for most tasks, in this case I'd drop it down to C. That'd give us the most leash and would still let us easily write solid OO implementations where deemed suitable. (a lot like linux kernel has been done)
One might ask that what's there to drop down from C++ to C, well I'll tell you, style. Object orientation using C is far more adaptive for strict memory usage than with ordinary classes in C++. Moreover lot of the benefits in C++ don't really come in handy when writing a kernel.
Re:Not really the point. (Score:2)
Re:Not really the point. (Score:1)
I am very hesitant to trust templates in large production code. Really that comes more from bad implementations (MS) but it also comes from the notion that I can write faster code myself. Even with the casts. I know that this statement flys in the face of reuse but there are quite a few people like me who do not think that OO has really helped with reuse that much. I still copy and paste and so do a lot of the coders that I know. Too deep of an inheritance tree will bring a lot of baggage and even worse sometimes undocumented baggage.
Java does not really "need" templates so much I think. Maybe better casting syntax like C++. I really like the static_cast syntax better than the parens... really just easier on the eyes to be honest.
The interesting thing about templates is to see how is it implemented. Did they break compatibility with existing JVM instructions? That is the interesting part. I think that you could implment templates without any changes to the underlying JVM and make the compiler do the work.
Anyway it will be interesting but I would rather see Java go open source more than see templates brought into an already powerful language.
My two cents
Re:Not really the point. (Score:1)
Re:Not really the point. (Score:2)
Or JNI over to C/C++ at least.
Dave
Re:Not really the point. (Score:2)
FFS
Good, and when do we gets enumerated types? (Score:2, Interesting)
Now, how many years do we have to wait until they do the same with the good old enum type?
Pascal
Re:Good, and when do we gets enumerated types? (Score:1)
By "good" enum, I mean something akin to what exists in Ada / Pascal / Modula / Eiffel, not the lousy C/C++ construct.
Pascal
Re:Good, and when do we gets enumerated types? (Score:2, Informative)
Good, but need to avoid a few problems (Score:5, Informative)
Although I'm glad to see the introduction of templates, I'm also concerned about how some of the problems I've encountered with C++ templates will be avoided. The biggest problem I've encountered has been the lack of interface checking.
For example the templated function for_each(begin, end, function) iterates from 'begin' to 'end' calling 'function' on each item inbetween. However there is no mechanism to specify that the type of passed to 'begin' and 'end' must have an equality operator and an operator* and 'function' must take one parameter of the type returned by *begin. This can cause very strange compiler errors when a user tries to pass a variable that doesn't support the proper operations to be compatible with the function. These errors actually appear to occur within the templated code, not the user-written code and can make determining the cause of these errors very difficult.
The Boost Concept Check [boost.org] library provides a way for programmers writing templated C++ code to enforce the interface requirements on the templated parameters in a way that gives more informative error messages. However this is rarely used, even in the Boost libraries. The documentation on the Boost Concept Check [boost.org] gives a good example of the kind of errors that C++ programmers dread.
In order for Java templates to be successful they will need to provide some manner of enforcing requirements on the interface necessary for the templated code to work and provide useful errors at compile time if it doesn't.
Boost CC library is in GCC (Score:2)
Recent versions of GCC ship with a version of the Boost Concept Checks embedded in (and adapted to) libstdc++. You can turn it on with a #define, or turn it on all the time with a switch to the 'configure' script. The docs [gnu.org] explain how.
My own copy of GCC has the checks turned on permanently. Very useful.
They did (Score:1)
Re:Good, but need to avoid a few problems (Score:1)
Anyway, Java already has a long tradition of using interfaces properly (it even has its own keyword :), and I believe Java programmers better understand its proper use. Hence, overusing templates is less likely to occur in Java.
Obligatory "parametrics != generics" comment (Score:3, Informative)
Since no-one has yet pointed it out that I can see, it should be noted that what we're talking about here is parameterised types, and to a limited extent, parameterised methods. This is still quite some way from what you can do with serious generics in other languages.
There is an obvious comparison with C++ templates here, and although those are not the best generics around themselves, they do have a few very useful tricks up their sleeves. In Java, you can now do parameterised containers, and to a limited extent you can do generic algorithms, although the lack of things like operator overloading cripples these from birth. You can't, AFAICS, do some of the funky stuff with traits classes, and things like template metaprogramming, expression templates and Andrei's tricks combining templates and inheritance -- the stuff that's used in several of the best C++ libraries today to give them an edge -- are out of the question for now.
That's a shame, because one of the great things about C++ templates is that using them is pretty easy, but there's quite a bit of power under the hood for people actually implementing class and function templates, such as the designers of those libraries. That means improved performance and/or flexibility for Joe Developers everywhere, even if only a few people know and use the features under the hood.
Too little, too late (Score:4, Insightful)
Sun ignored requests from the developer community to extend the Java core language. Now they finally listen, after Microsoft copied Java with C# and added generics [microsoft.com]. This is why Java has gone from the hottest thing since Starbucks, to yet another language. They didn't listen to their user base until 2 years after it was too late.
Lessons learned:
This is also why Microsoft is so successful - they constantly innovate, rather than sitting on their market dominance. I foresee Sun suddenly trying to play catch-up with new core Java features. I will enjoy reading the spin Sun puts on this, after saying for years that none of these features were necessary.
Re:Too little, too late (Score:4, Informative)
--
Re:Too little, too late (Score:4, Informative)
Next version of C# will support generics in the VM and that will remove the need for casts and allow you to do other nifty stuff like polymorphic recursion, getting specific runtime information that Vector is really that and not a Vector - in Java, you would have to look at the actual elements to determine that.
In fact, Microsoft Research people that presented a paper on generics in
Re:Too little, too late (Score:1, Informative)
Please explicate (Score:2)
Re:Too little, too late (Score:3, Interesting)
Sure they do. Microsoft is extremely good at seeing what other people are doing and, then, copying, buying, or squashing it to meet their agenda. In the case of C#, they first inhibited Java with their VM "embrace and extend" scheme, and then took Java, copied it, renamed it, and added a few things.
I guess you could call standing on other peoples shoulders innovation, but that is a relatively weak use of the word. Microsoft is more like the business partner that is your friend right up to the point of stabbing you in the back and taking credit for your work.
As for real innovation, I often wonder what "killer apps" were stifled over the years by Microsoft. Like weeds in a garden, Microsoft is always there...
Re:Too little, too late (Score:2)
I explicitly said that Microsoft embraced and extended Java. But all innovation is improving on existing ideas and adding your own. From the Franklin stove to alternative-fuel cars, to programming languages. The point is laziness. It took Sun 5 years to add templates to Java. In that same time span, Microsoft duplicated everything Java had, and more. Like it or not, that's a road to success.
Re:Too little, too late (Score:2)
I like OE. It has a clean UI, but it really hasn't changed since I started using it.
The only really neat feature they did add was the junk filter, and that got removed thanks to some moron e-card quasi-spammer.
Re:Too little, too late - it's natural to leapfrog (Score:1)
Re:Constantly innovate? Too late!!! (Score:1)
Re:Constantly innovate? Too late!!! (Score:2, Insightful)
Bjarne was right! :) (Score:2, Interesting)
Adding Generics Forum (Score:2)
Info + IDE supporting Java Generics (Score:2)
The preliminary spec for generic types in Java is here [jcp.org].
The Sun prototype compiler can be downloaded here [sun.com].
And a forum for discussion of Java generics is also available [sun.com].
You might also want to check out CodeGuide [omnicore.com]. This is AFAIK the only IDE which already supports Java generics as described in the spec (and is an awesome IDE for traditional Java as well).
Enjoy!
-- kryps
Java Evolving...to C++ (Score:2)
And really...the more of those missing features get added to Java, the more it gets to look like that other object oriented language with a syntax like C's...I believe it is called C++. Yes, I know objects are optional in C++, but they are in Java, too. int, float, etc. are simple types. Java is big, bloated, slow (yes it is) and a pain to program due to missing features. Once the missing features are added, and the speed is brought on par with other languages through compiling to native code, it will be just like C++. It won't be more portable, either. As far as I am concerned, Java is an expiriment, a failed experiment, to be exact. Go Python!!
Re:Some Java Generics problems (Score:2, Insightful)
Which doesn't change anything, because Java in general is unsuitable for high-performance scientific programming.
Generics aren't the only addition (Score:1)
There's a bit at the end of this article [sun.com].
It doesn't mention this specifically, but it alludes to also including static imports, foreach-like construct, and possibly enums.