Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JSR-000014 (generic classes) -- it's still not too late!

6 views
Skip to first unread message

Jorn W Janneck

unread,
Jun 6, 2001, 2:05:44 AM6/6/01
to
hi everybody.

as you may or may not have noticed, the jsr (java specification request,
i.e. a proposed extension to the java language) concerning the addition of
generic classes is in public review.

i think those of us who are going to use this language in the future may be
interested in exerting whatever little influence we have on the process,
because in my view that the current proposal is a very big mistake, and once
accepted will not only adversely affect the expressiveness of the java
language, but maybe even more importantly further distort the public view on
what generic types are and can be (pretty much like c++ templates did, whose
defects dominate the vast majority of discussions on the issue).

so in a sense this can be an important juncture in the design of the java
language, and i would like to encourage you to take an active interest in
the issue. for starters, you will probably want to review the current
proposal itself:

http://jcp.org/aboutJava/communityprocess/review/jsr014/

then you will want to check the orginal request:

http://jcp.org/jsr/detail/14.jsp

the current proposal has a lot in common with GJ (generic java), which can
be found here:

http://www.cs.bell-labs.com/who/wadler/pizza/gj/index.html

a critique of GJ, and a prototypical alternative (albeit in an outdated
version of java) can be found on the PolyJ site:

http://www.pmg.lcs.mit.edu/polyj/

here are a few reasons why i think that the current proposal is a big
mistake:

the original request quoted the following design goals:

<quote>
b) Type parameters (e.g., T) should be first-class types.
(A consequence of this is that List<T> is a first class type).
By "first-class" we mean that these new sorts of type expressions can be
used in exactly the same ways as existing type expressions. In particular,
it should be possible to cast a value expression to one of these sorts of
types, and to test whether an object is an instance of such a type.
c) Reflection should recognize generic type definitions, and provide
accurate information about formal type parameters in classes, interfaces and
methods
</quote>

it explicitly did *not* include the following:

<quote>
It is explicitly not required that the system

a) Provide downward binary compatibility: It is not necessary that class
files compiled under the generic compiler should run on previous releases,
whether they use generics or not.
</quote>

the current proposal does not answer the request -- it violates the
requirements (b) and (c) above, in order to obtain (a) below. the reason is
that List<Integer> (say) is *not* a proper type, the way String is, or
Object, or Boolean [ ]. it is not represented at runtime as a class object,
and thus contrary to all other (object) types, there is no way that i can
distinguish, at runtime, an instance of class List<Integer> from an instance
of List<String> -- if i do getClass() on either object, i get the same
List.class class object.

this has several deep consequences.

(1) for the first time in java, an object does not carry its complete type
information around. this means that reflection is no longer complete -- the
get-method of the class of an instance of List<String> has return type
Object, rather than String (e.g.).

(2) downcasting becomes a lot more complex. i cannot simply downcast any
Object to, say, Map<String, Integer>, because there is no way that i could
check this at runtime. the result is a set of complicated rules governing
when i can downcast to a parametric type (cf. 5.3 in the proposal).

(3) because things compile to regular jvm code, including all its
typechecks, one of the potential benefits of generic types, viz. removing
casts, cannot be realized. the casts are removed from the source-code, but
they are automatically compiled into the bytecode. so even though the need
to type them goes away, the runtime issue remains. (even though this is not
a very big point, it *is* ugly, and small machines might very well benefit
from the removal of casts.)

(3a) even worse though is this -- generic classes are normal java classes,
i.e. they can be used without parameterizing them. because typecasts are
implicit, we can now (for the almost first time, see 4) have a situation
where a class cast exception is thrown without a cast being present in the
source.

(4) the decision not to make parameterized classes proper classes (i.e.
represent them with distinct class objects) is also inconsistent with the
way arrays are treated in java. arrays can be seen as a small specialized
form of generic classes, and A [] iand B [] are different classes:
A [] a = new A[1]; B[] b = new B [1];
System.out.println(a.getClass() == b.getClass())

so please let us discuss this proposal here, and maybe come up with
something better. maybe we can even form a small group of people interested
in this matter, and submit our objections to sun. the closing date is august
01, so we need to hurry somewhat.

best regards,

-- j


Artur Biesiadowski

unread,
Jun 6, 2001, 8:15:28 AM6/6/01
to

I see your points, but you forget to mention one thing. If we would
choose your way (separate class for every type) we would end up with
very bloated runtime. Currently amount of classes loaded/created is main
reason for bad responsivness and lengthy startup of java. Having
non-trivial classes duplicated (and collections are non-trivial) would
only worsen the situation. Every type of same collection would have to
be jitted separately. Note that except removing typecasts (which can be
very fast in java) it would not provide any speedup - you cannot rely on
having textual binding of methods like in C++ templates. In java you
have to use some common subclass/interface to access properties - and if
you do this, you do not really have to specialize per type.

Yes, having exact types on instances of generic classes would be nice.
But I think it is better to have smaller runtime hit and share jitted
code then to create separate classes.

Artur

Jason Russ

unread,
Jun 6, 2001, 9:18:50 AM6/6/01
to
How do we vote against this?

I have been against this idea ever since
I saw GJ presented at OOPSLA in 1997.

Mats Olsson

unread,
Jun 6, 2001, 9:55:38 AM6/6/01
to
In article <3B1E1EE0...@pg.gda.pl>,

Artur Biesiadowski <ab...@pg.gda.pl> wrote:
>
>I see your points, but you forget to mention one thing. If we would
>choose your way (separate class for every type) we would end up with
>very bloated runtime. Currently amount of classes loaded/created is main
>reason for bad responsivness and lengthy startup of java. Having
>non-trivial classes duplicated (and collections are non-trivial) would
>only worsen the situation. Every type of same collection would have to
>be jitted separately.

Hmm... not necessarily. A List<String> would be a new class instance,
but it would be a very small instance - just enough to point to the real
class and store the type parameter list. So instantiating a List<String>
would be very cheap, memory and CPU wise - it would just piggyback on
the List class.

However, this does make the class file format non-backwards compatible,
and require modified classloaders/JIT compilers etc. Lots and lots of work.

If I understand it correctly, the real problem with the current
proposal is this:

public void main(String[] args) {
Object o1 = new List<Integer>();

// the following line won't give a runtime error, because at runtime,
// it's just says "List l2 = (List) o1;"
List<String> l2 = (List<String>) o1; // no error.

l1.add(new Integer(1));

// And _here_ is where you will get the runtime error. Now imagine'
// that you have passed around the list through multiple levels of
// library and API-calls, all saying that they require a List<String>,
// but in reality just requiring a List... it might be a bit
// hard to understand just where someone managed to insert an Integer
// into a list of strings.
String s = l2.get(0);

// Compare this with
Object o2 = new Integer[] { new Integer(1); }
// In this case, you get the runtime error directly where the error
// is committed, right here
String[] a2 = (String[]) o2;
// ... so this can never be wrong.
String s = a2[0];
}

*snip*


>Yes, having exact types on instances of generic classes would be nice.
>But I think it is better to have smaller runtime hit and share jitted
>code then to create separate classes.

The intention is to have the cake and eat it too ... :-) unfortunately,
that's a lot more work than doing the currently proposed way.

OTOH, it's not going in until 1.5 anyhow, so there should be time...
and there is no better time than now, really. Better to have more pain
now and a less painful future than to accept a quick fix that you will
have to live with forever more.

In fact, I'd propose ramming Gosling word's right back at them -
wasn't it something like 'better wait and do it right than accept the
quick and easy fix'...?

At the minimum, I'd ask for a commitment that generic types will
become first class types in the future. Ie, that the weaknesses of
the current proposal is acknowledged and a fix promised. Thus, any code
depending on List<Integer>.class == List<String>.class must be regarded
as buggy.

/Mats

Artur Biesiadowski

unread,
Jun 6, 2001, 10:48:00 AM6/6/01
to

Mats Olsson wrote:


> // the following line won't give a runtime error, because at runtime,
> // it's just says "List l2 = (List) o1;"
> List<String> l2 = (List<String>) o1; // no error.

But it gives warning at compile time. Something like "Cast at line XX
cannot be checked - be careful". It clearly marks parts where generic
assumptions can be broken. Yes, it is not as good as getting same thing
at runtime, but I think it should be enough in most cases.

Artur

Jorn W Janneck

unread,
Jun 6, 2001, 12:24:45 PM6/6/01
to

"Artur Biesiadowski" <ab...@pg.gda.pl> wrote in message
news:3B1E1EE0...@pg.gda.pl...

>
> I see your points, but you forget to mention one thing. If we would
> choose your way (separate class for every type) we would end up with
> very bloated runtime. Currently amount of classes loaded/created is main
> reason for bad responsivness and lengthy startup of java. Having
> non-trivial classes duplicated (and collections are non-trivial) would
> only worsen the situation. Every type of same collection would have to
> be jitted separately.

why is that so? the code in each would of course be identical. in fact,
there would probably only be one instance of that code.

and it is not that we do not have this already -- this is precisely what
happens in the case of arrays.

> Note that except removing typecasts (which can be
> very fast in java) it would not provide any speedup - you cannot rely on
> having textual binding of methods like in C++ templates. In java you
> have to use some common subclass/interface to access properties - and if
> you do this, you do not really have to specialize per type.

i did not understand this point.

best regards,

-- j

ps: btw, calling it 'my way' gives me undue credit -- this is, e.g., the way
polyj does it. or in fact the way java does it, for arrays.

Jorn W Janneck

unread,
Jun 6, 2001, 12:25:42 PM6/6/01
to

"Jason Russ" <jason...@home.com> wrote in message
news:3B1E3B8D...@home.com...

> How do we vote against this?
>
> I have been against this idea ever since
> I saw GJ presented at OOPSLA in 1997.
>

there is no vote as such, but you can send your comments to the public
review.

best regards,

-- j

Jorn W Janneck

unread,
Jun 6, 2001, 12:34:50 PM6/6/01
to

"Artur Biesiadowski" <ab...@pg.gda.pl> wrote in message
news:3B1E42A0...@pg.gda.pl...

well, it enormously complicates the language. up to now, a cast is a cast is
a cast. with this concept, you have to teach people how to interpret those
compiler warnings, and that there are two kinds of types, 'real' ones, and
this other kind, the exact semantics of which i would not want to have to
explain to a beginner. or anybody else, for that matter.

so what does 'be careful' mean, operatively? what else can i do, here, to be
careful? currently, decorating my code with instanceof/casts etc. was as
careful as i can be, and something parametric types were supposed to get rid
of, at least partly.

what we are sacrificing here is a lot of language clarity and power for
implementation convenience and backward compatibility. java has done this
too often already, it's time to start doing the right thing.

regards,

-- j

Les Stroud

unread,
Jun 6, 2001, 12:36:28 PM6/6/01
to
Hmmm....
I certainly see your point. I am an OO biggot. Generics typically
lead to larger binaries and unmaintainable code. They definitely don't
make sense in the enterprise environment where the model is more
important than the implementation.

However, the adding of generics will allow java to approach the more
computational intense applications found in scientific and enginering.
Specifically, if you can acheive polymorphism around primitives then
you can employ some interesting compiler (jit not javac) optimizations
that will rival C++ and even Fortran in some instances. The overhead
of the object wrapper, as thin as it may be, makes it impossible to
manipulate numerics at the register and stack level. So, every call
to a Float will require context switches and memory access. As such,
java will be relegated to the enterprise environment where database
access is slower than object manipulation. Not that this is a bad
thing, but it limits the "java platform" to a niche (albeit a big
niche) market. I would suggest supporting this proposal and then use
coding standards in the enterprise environment to avoid them.

LES

"Jorn W Janneck" <jan...@REMOVETHIS-eecs.berkeley.edu> wrote in message news:<YKjT6.66898$%i7.50...@news1.rdc1.sfba.home.com>...

Phillip Lord

unread,
Jun 6, 2001, 1:21:18 PM6/6/01
to
>>>>> "Artur" == Artur Biesiadowski <ab...@pg.gda.pl> writes:

Artur> I see your points, but you forget to mention one thing. If we
Artur> would choose your way (separate class for every type) we
Artur> would end up with very bloated runtime. Currently amount of
Artur> classes loaded/created is main reason for bad responsivness
Artur> and lengthy startup of java.

This depends on how it is done of course. There was a cute
proposal a while back called "poor mans genericity" where they
achieved all of this with a modified class loader only (and compiler
of course!). Memory requirements are not affected seriously because
its possible to compress class definitions, and very similar
definitions will of course compress well.

Artur> Having non-trivial classes duplicated (and collections are
Artur> non-trivial) would only worsen the situation. Every type of
Artur> same collection would have to be jitted separately.

This would only be true for JVM's which did not understand
genericity. Backwards compatibility can would be maintained but it
might be a little inefficient.

Phil

Jorn W Janneck

unread,
Jun 6, 2001, 1:25:46 PM6/6/01
to

"Les Stroud" <les_s...@hotmail.com> wrote in message
news:4553f209.01060...@posting.google.com...

> Hmmm....
> I certainly see your point. I am an OO biggot. Generics typically
> lead to larger binaries

that's what i mentioned, one of those things c++ templates has left us with.
in the java context, the binaries would rather get smaller than larger.

> and unmaintainable code.

how so? the code now expresses more static type information. or rather, it
usually expresses the same type information, but more of it is statically
checkable. how can that be a bad thing?

> They definitely don't
> make sense in the enterprise environment where the model is more
> important than the implementation.

this is odd. i would have thought that this is precisely the strength of
generic classes -- allowing you to express more 'conceptual' knowledge in
you code directly.

Map<String, Integer> m;

is a lot clearer to me than

Map m;

> However, the adding of generics will allow java to approach the more
> computational intense applications found in scientific and enginering.
> Specifically, if you can acheive polymorphism around primitives then
> you can employ some interesting compiler (jit not javac) optimizations
> that will rival C++ and even Fortran in some instances. The overhead
> of the object wrapper, as thin as it may be, makes it impossible to
> manipulate numerics at the register and stack level. So, every call
> to a Float will require context switches and memory access. As such,
> java will be relegated to the enterprise environment where database
> access is slower than object manipulation. Not that this is a bad
> thing, but it limits the "java platform" to a niche (albeit a big
> niche) market. I would suggest supporting this proposal and then use
> coding standards in the enterprise environment to avoid them.

you have misunderstood me, i think. i am all *for* adding generics to java,
in fact i have gotten a lot of flak for it in this group since i advocated
it years ago. i am just for doing it right rather than wrong. and yes,
rather than doing it wrong, i'd not do it at all, because that at least
leaves open the possibility for doing it right later.

but this is not what i am arguing here. i would like people to get together
and suggest how to do it right, and voice their dissatisfaction with the way
it is proposed to be done.

then, the current proposal specifically does not involve primitive types.
that's a pity, but i think a defensible design decision. i would rather see
this fixed by sometime elevating primitive types to (conceptual) proper
objects, than making the generic classes design more complex because of it.

furthermore, there is no *object* wrapper. there is most likely a very
lightweight *class* wrapper, such as there is for arrays at the moment.

finally, i do not quite understand your performance argument.

List<Integer> l = new List<Integer>();
...
l.get(0);

where is the additional overhead here?

best regards,

-- j


Phillip Lord

unread,
Jun 6, 2001, 1:26:18 PM6/6/01
to
>>>>> "Jorn" == Jorn W Janneck <jan...@REMOVETHIS-eecs.berkeley.edu> writes:

>> But it gives warning at compile time. Something like "Cast at
>> line XX cannot be checked - be careful". It clearly marks parts
>> where generic assumptions can be broken. Yes, it is not as good
>> as getting same thing at runtime, but I think it should be enough
>> in most cases.

Jorn> well, it enormously complicates the language. up to now, a
Jorn> cast is a cast is a cast. with this concept, you have to teach
Jorn> people how to interpret those compiler warnings, and that
Jorn> there are two kinds of types, 'real' ones, and this other
Jorn> kind, the exact semantics of which i would not want to have to
Jorn> explain to a beginner. or anybody else, for that matter.

I am not sure that this is true. Paramaterised typing is a
fairly old technology and reasonably well understood, and not that
hard to teach. Certainly there is experience in teaching it.

Also I think that its most likely that beginners will be
instantiating classes which are parameterised, rather than creating
them, so its less of a problem.


Jorn> so what does 'be careful' mean, operatively? what else can i
Jorn> do, here, to be careful? currently, decorating my code with
Jorn> instanceof/casts etc. was as careful as i can be, and
Jorn> something parametric types were supposed to get rid of, at
Jorn> least partly.

Jorn> what we are sacrificing here is a lot of language clarity and
Jorn> power for implementation convenience and backward
Jorn> compatibility. java has done this too often already, it's time
Jorn> to start doing the right thing.

This is true of course. It would be nice to remove the cast
entirely, but of course this is totally non backwards
compatible. Generally speaking you should only get unchecked warnings
when you are creating generic classes, rather than using them. I
agree that it would be nice to have a cleaner system than
this. However sacrificing backwards compatibility is not going to
happen. Under the circumstances I would rather than a reasonable if
slightly messy genericity system, than none at all.

Phil

Phillip Lord

unread,
Jun 6, 2001, 1:34:16 PM6/6/01
to
>>>>> "Les" == Les Stroud <les_s...@hotmail.com> writes:

Les> Hmmm.... I certainly see your point. I am an OO
Les> biggot.

I am a little confused by this statement. Are you trying
to suggest that an expressive type system and object orientation are
contradictory. As far as I can see they work very well together.

Les> Generics typically lead to larger binaries and unmaintainable
Les> code.

The current proposal should not result in larger binary
sizes. Unmaintainable code? I just don't understand this. Having a
decent type system that gives you compile time error checking should
reduce maintainability concerns.


Les> They definitely don't make sense in the enterprise environment
Les> where the model is more important than the implementation.

Again I can not see what you are getting at. I would like to
parameterise over the interface definitions, even when I don't care
what the implementation is.


Les> However, the adding of generics will allow java to approach the
Les> more computational intense applications found in scientific and
Les> enginering.

Unfortunately the current proposal does not really have much
impact on computational intensity, as it all happens at compile
time. Underneath its implemented using casts.


Les> Specifically, if you can acheive polymorphism around primitives

You can't with the current proposal.


Les> The overhead of the object wrapper, as thin as it may be, makes
Les> it impossible to manipulate numerics at the register and stack
Les> level.

I think that numerical Java proposal should impact on
computational performance. Its a little outside my field
though, so I am not sure.


Les> (albeit a big niche)

I am not sure as to whether this is an oxymoron or not!


Phil

Phillip Lord

unread,
Jun 6, 2001, 1:45:36 PM6/6/01
to
>>>>> "Jorn" == Jorn W Janneck <jan...@NOSPAM-eecs.berkeley.edu> writes:

Jorn> you have misunderstood me, i think. i am all *for* adding
Jorn> generics to java, in fact i have gotten a lot of flak for it
Jorn> in this group since i advocated it years ago. i am just for
Jorn> doing it right rather than wrong. and yes, rather than doing
Jorn> it wrong, i'd not do it at all, because that at least leaves
Jorn> open the possibility for doing it right later.

I think that you are pissing into the wind here to be honest.
As I am sure that you are aware there have been a number of different
proposals for genericity of which GJ and PolyJ have been two. They had
their different strengths and weaknesses of course. In moving the
expert committee in the way that they did it was pretty clear that GJ
was going to be the system which ended up being implemented. The
reason for this is clear. Its backwards compatible. Genericity is not
considered to be important enough to most people to sacrifice
backwards compatibility for.

In short I think that you are trying to have an argument that
really has already been settled. Its unlikely to make much
difference.

Phil


Roedy Green

unread,
Jun 6, 2001, 3:18:26 PM6/6/01
to
On Wed, 06 Jun 2001 06:05:44 GMT, "Jorn W Janneck"
<jan...@REMOVETHIS-eecs.berkeley.edu> wrote or quoted :

>(1) for the first time in java, an object does not carry its complete type
>information around. this means that reflection is no longer complete -- the
>get-method of the class of an instance of List<String> has return type
>Object, rather than String (e.g.).

Uggh! Is a temporary kludge until a major revision when the JVM can
change, or is it something we will have to live with forever?

For more detail, please look up the key words mentioned in this post in
the Java Glossary at: http://mindprod.com/gloss.html
If you don't see what you were looking for, complain!
or send your contribution for the glossary.

--
Roedy Green, Canadian Mind Products
Custom computer programming since 1963. Ready to take on new work.

Roedy Green

unread,
Jun 6, 2001, 3:35:38 PM6/6/01
to
On 06 Jun 2001 18:21:18 +0100, Phillip Lord <p.l...@hgmp.mrc.ac.uk>
wrote or quoted :

> This would only be true for JVM's which did not understand
>genericity. Backwards compatibility can would be maintained but it
>might be a little inefficient.

Maintaining upward compatibility is obviously important. Maintaining
backward compatibility is a waste of time. There are so many problems
with class libraries, it is silly to waste time trying to make new
language feature code work on old JVMs.

The motive is to make it EASY for vendors to modify JVMs. MS
complained it was too tough to keep up with Sun's changes.

Every one of us can think of a dozen times when a "quick" and dirty
solution came back to haunt them over and over and over.

Murphy's law has a way of cementing any kludge in place. Windows
95/98/ME is a classic case.

I hope Sun has carefully planned its future escape from this kludge.

Glenn G. D'mello

unread,
Jun 6, 2001, 4:02:03 PM6/6/01
to
Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote in
news:vfd78hj...@cs.man.ac.uk:

<<Snip>>

> them. I agree that it would be nice to have a cleaner system than
> this. However sacrificing backwards compatibility is not going to
> happen. Under the circumstances I would rather than a reasonable if

Hasn't this already happened with 1.2? (witness the -target command
line option to javac)! So, maybe 1.5 should 'do the right thing' by
default with an option for backward compatibility to be used where
required.

Hmm. I'm begining to really like this idea... :)

Glenn/

--
Apologies. Due to the insane amounts of spam I get on every post to
usenet, mail sent to the posting address is delivered to /dev/null.
Post to the group or use my name at my sending domain for emailing.

Matt Kennel

unread,
Jun 6, 2001, 4:47:09 PM6/6/01
to
On 6 Jun 2001 09:36:28 -0700, Les Stroud <les_s...@hotmail.com> wrote:
:Hmmm....

:I certainly see your point. I am an OO biggot. Generics typically
:lead to larger binaries and unmaintainable code.

I see the first---but why the second?

:They definitely don't


:make sense in the enterprise environment where the model is more
:important than the implementation.

Why?

:However, the adding of generics will allow java to approach the more


:computational intense applications found in scientific and enginering.

Not without user-defined value types in addition.

: Specifically, if you can acheive polymorphism around primitives then


:you can employ some interesting compiler (jit not javac) optimizations
:that will rival C++ and even Fortran in some instances. The overhead
:of the object wrapper, as thin as it may be, makes it impossible to
:manipulate numerics at the register and stack level. So, every call
:to a Float will require context switches and memory access. As such,
:java will be relegated to the enterprise environment where database
:access is slower than object manipulation. Not that this is a bad
:thing, but it limits the "java platform" to a niche (albeit a big
:niche) market. I would suggest supporting this proposal and then use
:coding standards in the enterprise environment to avoid them.
:
:LES

:> the current proposal does not answer the request -- it violates the

oh my god this is insane.

--
* Matthew B. Kennel/Institute for Nonlinear Science, UCSD
*
* "To chill, or to pop a cap in my dome, whoomp! there it is."
* Hamlet, Fresh Prince of Denmark.

Jorn W Janneck

unread,
Jun 6, 2001, 5:26:39 PM6/6/01
to

"Phillip Lord" <p.l...@hgmp.mrc.ac.uk> wrote in message
news:vf1yoxj...@cs.man.ac.uk...
[snip]

> I think that you are pissing into the wind here to be honest.
> As I am sure that you are aware there have been a number of different
> proposals for genericity of which GJ and PolyJ have been two. They had
> their different strengths and weaknesses of course. In moving the
> expert committee in the way that they did it was pretty clear that GJ
> was going to be the system which ended up being implemented. The
> reason for this is clear. Its backwards compatible. Genericity is not
> considered to be important enough to most people to sacrifice
> backwards compatibility for.
>
> In short I think that you are trying to have an argument that
> really has already been settled. Its unlikely to make much
> difference.

i agree with you, and also with the reasons you give. i am well aware of the
chances of success, but since it doesn't cost that much, and since the
potential difference to make here is huge, it might just be worth it.

regards,

-- j

Jorn W Janneck

unread,
Jun 6, 2001, 5:28:27 PM6/6/01
to

"Roedy Green" <ro...@mindprod.com> wrote in message
news:qd0tht8a8h0sqk7o0...@4ax.com...

> On Wed, 06 Jun 2001 06:05:44 GMT, "Jorn W Janneck"
> <jan...@REMOVETHIS-eecs.berkeley.edu> wrote or quoted :
>
> >(1) for the first time in java, an object does not carry its complete
type
> >information around. this means that reflection is no longer complete --
the
> >get-method of the class of an instance of List<String> has return type
> >Object, rather than String (e.g.).
>
> Uggh! Is a temporary kludge until a major revision when the JVM can
> change, or is it something we will have to live with forever?

that's just the point -- once it's there, it will be a solution that does
som half-a**ed job and nobody will want to change the jvm for a difference
that it hard to explain to 90% of the java community (that's what is
scientifically called a 'wild guess'...) in the first place.

it will stay with us.

regards,

-- j


Jorn W Janneck

unread,
Jun 6, 2001, 5:41:49 PM6/6/01
to

"Phillip Lord" <p.l...@hgmp.mrc.ac.uk> wrote in message
news:vfd78hj...@cs.man.ac.uk...

> >>>>> "Jorn" == Jorn W Janneck <jan...@REMOVETHIS-eecs.berkeley.edu>
writes:
[snip]

> Jorn> well, it enormously complicates the language. up to now, a
> Jorn> cast is a cast is a cast. with this concept, you have to teach
> Jorn> people how to interpret those compiler warnings, and that
> Jorn> there are two kinds of types, 'real' ones, and this other
> Jorn> kind, the exact semantics of which i would not want to have to
> Jorn> explain to a beginner. or anybody else, for that matter.
>
> I am not sure that this is true. Paramaterised typing is a
> fairly old technology and reasonably well understood, and not that
> hard to teach. Certainly there is experience in teaching it.

but my point was not that parametric types are the issue, but rather that
the rules governing their use due to the awkwardnesses of the current
proposal, and complicate the matter considerably.

> Also I think that its most likely that beginners will be
> instantiating classes which are parameterised, rather than creating
> them, so its less of a problem.

the issue i raised concerned the *use* of parametric classes, rather than
their creation.

also, the fact that inexperienced programmers think that generic classes are
black magic is pretty much due to the fact that in c++ they are. in other
languages, eiffel and haskell, e.g., people get exposed to the issue very
early on, and usually have no problem dealing with it. because, as you say,
genericity as such is nothing new, and also nothing all too hard to figure
out, but certain implementations of it *mae* it hard. and so does the one
currently proposed.

> Jorn> so what does 'be careful' mean, operatively? what else can i
> Jorn> do, here, to be careful? currently, decorating my code with
> Jorn> instanceof/casts etc. was as careful as i can be, and
> Jorn> something parametric types were supposed to get rid of, at
> Jorn> least partly.
>
> Jorn> what we are sacrificing here is a lot of language clarity and
> Jorn> power for implementation convenience and backward
> Jorn> compatibility. java has done this too often already, it's time
> Jorn> to start doing the right thing.
>
> This is true of course. It would be nice to remove the cast
> entirely, but of course this is totally non backwards
> compatible. Generally speaking you should only get unchecked warnings
> when you are creating generic classes, rather than using them. I
> agree that it would be nice to have a cleaner system than
> this. However sacrificing backwards compatibility is not going to
> happen. Under the circumstances I would rather than a reasonable if
> slightly messy genericity system, than none at all.

i disagree. so did sun already once.

regards,

-- j

Jorn W Janneck

unread,
Jun 6, 2001, 5:42:29 PM6/6/01
to

"Glenn G. D'mello" <dev...@dmello.org> wrote in message
news:Xns90B88436D9E9...@0.0.0.1...

> Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote in
> news:vfd78hj...@cs.man.ac.uk:
>
> <<Snip>>
>
> > them. I agree that it would be nice to have a cleaner system than
> > this. However sacrificing backwards compatibility is not going to
> > happen. Under the circumstances I would rather than a reasonable if
>
> Hasn't this already happened with 1.2? (witness the -target command
> line option to javac)! So, maybe 1.5 should 'do the right thing' by
> default with an option for backward compatibility to be used where
> required.
>
> Hmm. I'm begining to really like this idea... :)

this is great glenn. send them a letter. maybe by harassing them a little
bit...

cheers,

-- j


Jorn W Janneck

unread,
Jun 6, 2001, 6:49:48 PM6/6/01
to

"Artur Biesiadowski" <ab...@pg.gda.pl> wrote in message
news:3B1E42A0...@pg.gda.pl...
>
>
> Mats Olsson wrote:
>
>
> > // the following line won't give a runtime error, because at
runtime,
> > // it's just says "List l2 = (List) o1;"
> > List<String> l2 = (List<String>) o1; // no error.
>
> But it gives warning at compile time. Something like "Cast at line XX
> cannot be checked - be careful".

another thought on this:

right now, for this code

(T)expr

there are two possibilities: either the type of the object computed by expr
is a subtype of T (in which case the cast succeeds) or not (in which it
fails). the second case has two subcases: either the compiler can figure out
that it will go wrong, as in

(Integer)"String"

in which case it will tell you, or it cannot. *the whole point* of type
casting is to weed out this last subcase. that's the raison d'etre for this
construct. to check something at runtime that cannot be checked at compile
time. while somewhat kludgy from the type system point of view, i think
there is practical justification for it.

now, we have a kind of typecast that we cannot say will fail, but because we
cannot ascertain that it will succeed, we throw a warning or an error. huh?
so we are now statically checking dynamic type checks?

i think that the current rule for casting is pretty easy to explain to
people, once they have understood the notion of polymorphism (i know this
for a fact, as i have done this for several years). however, i would not
want to have to explain the proposed solution to newcomers -- they would
have a hard time with it, and rightly so. it *is* confusing.

> It clearly marks parts where generic
> assumptions can be broken. Yes, it is not as good as getting same thing
> at runtime, but I think it should be enough in most cases.

well, it's not. there are two cases: either you plainly disallow these
casts, in which case you cannot do this:

void f(Object a) {
List<Integer> lst = (List<Integer>)a;
... // do something
}

however, this is perfect java code:

void f(Object a) {
List lst = (List)a;
... // do something
}

otoh, if you allow this first code to compile (with a warning, that you
disregard), then i can use your f method later on from my code as follows:

void g() {
List<String> lst = new List<String>();
...
f(lst);
// remember, we are nicely backward compatible, so
// there is no way to check this directly in f, as
// a string list is indistinguishable from and integer
// list.
}

in the best case, this will give me a pretty stack trace starting in your f,
whose contract i violated. but it's just as likely that your f passed the
list around your code, and only when someone finally extracted an element
will a cast be applied and then the stack trace starts there. in fact, this
may well be any time after i called f (the list got stored, and later used).

don't know how you see this, but i think that's a pile of horse manure,
either way. if the compiler only produces a warning (my understanding is
that the proposal suggests to forbid those casts completely), the pile is
just quite a bit bigger, and reeks quite a bit more.

regards,

-- j

Artur Biesiadowski

unread,
Jun 6, 2001, 7:12:14 PM6/6/01
to

Jorn W Janneck wrote:

>
> what we are sacrificing here is a lot of language clarity and power for
> implementation convenience and backward compatibility. java has done this
> too often already, it's time to start doing the right thing.

There is one additional benefit on gj approach. You can ignore it
entirely, DO NOT use generics in proposed way and interface to code
which uses generics, still without having to use them. So if you don't
want, NOTHING has changed. With another approach you would be actually
forced to use generics if some third part lib would use them. Now it is
optional. I think it is really a great thing, being able to interface
generic and non-generic code without any problems (except these special
compiler-only casts List -> List<String> in few places).


Artur

Mats Olsson

unread,
Jun 6, 2001, 7:32:54 PM6/6/01
to
In article <3B1E42A0...@pg.gda.pl>,

So, now we won't be able to write correct programs that requires the
use of these casts cleanly... _not_ a win from where I'm standing... and
there will be lots of programs that requires it. Consider any program
using serialization, for example.

// the following will give you a warning. Even though there is no
// other bloody way of writing this code.
List<Integer> intList = (List<Integer>) objectInputStream.readObject();

Not a good solution. Also, any use of serialization means that you
can export data and shovel it around (using RMI for example), all looking
nice and typesafe until you find an Integer in your List<String>.

/Mats

Mats Olsson

unread,
Jun 6, 2001, 7:35:22 PM6/6/01
to
In article <9fmej6$f3b$1...@nyheter.chalmers.se>,

Mats Olsson <ma...@dtek.chalmers.se> wrote:
>In article <3B1E42A0...@pg.gda.pl>,
>Artur Biesiadowski <ab...@pg.gda.pl> wrote:
>>Mats Olsson wrote:
>>
>>
>>> // the following line won't give a runtime error, because at runtime,
>>> // it's just says "List l2 = (List) o1;"
>>> List<String> l2 = (List<String>) o1; // no error.
>>
>>But it gives warning at compile time. Something like "Cast at line XX
>>cannot be checked - be careful". It clearly marks parts where generic
>>assumptions can be broken. Yes, it is not as good as getting same thing
>>at runtime, but I think it should be enough in most cases.
>
> So, now we won't be able to write correct programs that requires the
^^^^^
eh... compile

Roedy Green

unread,
Jun 6, 2001, 7:35:55 PM6/6/01
to
On Thu, 07 Jun 2001 01:12:14 +0200, Artur Biesiadowski
<ab...@pg.gda.pl> wrote or quoted :

>There is one additional benefit on gj approach. You can ignore it
>entirely, DO NOT use generics in proposed way and interface to code
>which uses generics, still without having to use them.

Could you expound on that with an example?

Mats Olsson

unread,
Jun 6, 2001, 7:43:04 PM6/6/01
to
In article <4553f209.01060...@posting.google.com>,

Les Stroud <les_s...@hotmail.com> wrote:
>Hmmm....
>I certainly see your point. I am an OO biggot. Generics typically
>lead to larger binaries and unmaintainable code.

You are thinking of templates a'la C++, where each templated class
(typically) replicates the code. The proposed Java generics is much
less complex and less powerful, only adding type-safety at compile
time and only for objects, not primitive values.

/Mats

Jorn W Janneck

unread,
Jun 6, 2001, 7:48:03 PM6/6/01
to

"Artur Biesiadowski" <ab...@pg.gda.pl> wrote in message
news:3B1EB8CE...@pg.gda.pl...

i agree with you on the value of being able to ignore it, but i am not sure
that this could not be achieved to a useful degree using proper parametric
type objects. List, e.g. could still be shorthand for a type, e.g.
equivalent to List<Object>.

-- j

Mats Olsson

unread,
Jun 6, 2001, 8:12:34 PM6/6/01
to
In article <ehfthtgep9nehi2fj...@4ax.com>,

Roedy Green <ro...@mindprod.com> wrote:
>On Thu, 07 Jun 2001 01:12:14 +0200, Artur Biesiadowski
><ab...@pg.gda.pl> wrote or quoted :
>
>>There is one additional benefit on gj approach. You can ignore it
>>entirely, DO NOT use generics in proposed way and interface to code
>>which uses generics, still without having to use them.
>
>Could you expound on that with an example?

If I write a class that takes List<Integer> as an argument and hand
the .class file to you, you can ignore generics completly and just call
it with a List object, without bothering even to cast it to a parameterized
type. At least if you are using a non-generics compiler... it won't look
at the .class file section that details the generics info.

In the current proposal, a List containing Integers can be cast to
a List<Integer>. If List<Integer> was its own class, the only way to
make a List of Integers a List<Integer> would be to create a new
List<Integer> and move the contents of the original list to the
new List<Integer>. Ie, analogous to the reason why an Object[] array
contain Integers can't be cast to an Integer[] array.

/Mats

Jorn W Janneck

unread,
Jun 6, 2001, 8:19:46 PM6/6/01
to

"Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
news:9fmgti$f7e$1...@nyheter.chalmers.se...

i know what you mean, and it's correct, but this related example works:

Object [] a = new Integer[10];

Integer[] b = (Integer[]) a;

it would not work in all cases in the generics proposal.

regards,

-- j

Mats Olsson

unread,
Jun 6, 2001, 8:38:12 PM6/6/01
to
In article <9fmh5c$1glr$1...@agate.berkeley.edu>,

Jorn W Janneck <jan...@NOSPAM-eecs.berkeley.edu> wrote:
>
>"Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
>> new List<Integer>. Ie, analogous to the reason why an Object[] array
>> contain Integers can't be cast to an Integer[] array.
>
>i know what you mean, and it's correct, but this related example works:
>
>Object [] a = new Integer[10];
>
>Integer[] b = (Integer[]) a;
>
>it would not work in all cases in the generics proposal.

Something like this, you mean?

List l = new List<Integer>(); // warning here
l.add("a string"); // no warning
List<Integer> l2 = (List<Integer>) l;
List<String> l3 = (List<String>) l; // well, why not?
String s = l3.get(0); // works real nice
Integer i = l2.get(0); // crash here

Object[] a = new Integer[10];

a[0] = "a string"; // crash here


Integer[] b = (Integer[]) a;

/Mats

Bart.Van...@nowhere.be

unread,
Jun 6, 2001, 4:48:44 PM6/6/01
to
Les Stroud <les_s...@hotmail.com> wrote:
> I certainly see your point. I am an OO biggot. Generics typically
> lead to larger binaries and unmaintainable code. They definitely don't

Generics certainly lead to bigger binaries although that's only a problem
in the embedded world. (Hands up any of you who have inherited from
a standard collection just to avoid the typecasts and be sure of what's
in a certain collection at runtime. I know I have and thus I know the
bloat is (partly) already there in my programs.)

But I find e.g. generic collections much clearer than their type-amorf
variants with the associated type-cast hell.

> make sense in the enterprise environment where the model is more
> important than the implementation.

I think this statement is based on personal preference and not on
facts.

> However, the adding of generics will allow java to approach the more
> computational intense applications found in scientific and enginering.

No, it wont because the proposed addition to the standard doesn't
allow non-class types as type parameters for generic classes.

A big flaw indeed, but understandable, given the design decisions
of generic java.

> Specifically, if you can acheive polymorphism around primitives then
> you can employ some interesting compiler (jit not javac) optimizations
> that will rival C++ and even Fortran in some instances. The overhead

See http://oonumerics.org/blitz for more examples of what generic
programming can do for numerical applications.

cu bart

--
http://www.irule.be/bvh/

Bart.Van...@nowhere.be

unread,
Jun 7, 2001, 6:13:17 AM6/7/01
to
Mats Olsson <ma...@dtek.chalmers.se> wrote:
> If I write a class that takes List<Integer> as an argument and hand
> the .class file to you, you can ignore generics completly and just call
> it with a List object, without bothering even to cast it to a parameterized
> type. At least if you are using a non-generics compiler... it won't look
> at the .class file section that details the generics info.

What happens when you pass a List that contains more than just Integers?
Failed casts at runtime?

I don't see this as an advantage of the current proposal actually.

Phillip Lord

unread,
Jun 7, 2001, 6:58:56 AM6/7/01
to
>>>>> "Roedy" == Roedy Green <ro...@mindprod.com> writes:

Roedy> On 06 Jun 2001 18:21:18 +0100, Phillip Lord
Roedy> <p.l...@hgmp.mrc.ac.uk> wrote or quoted :

>> This would only be true for JVM's which did not understand
>> genericity. Backwards compatibility can would be maintained but
>> it might be a little inefficient.

Roedy> Maintaining upward compatibility is obviously important.
Roedy> Maintaining backward compatibility is a waste of time. There
Roedy> are so many problems with class libraries, it is silly to
Roedy> waste time trying to make new language feature code work on
Roedy> old JVMs.

I mostly agree with this, although rather than saying
backwards compatibility is a waste of time, I would say that the way
in which backwards compatibility is abandoned should be
transparent. So for instance they could have made it so that things to
be removed emit a warning on the release (ie like deprecation), and
then are removed in the next.

Roedy> I hope Sun has carefully planned its future escape from this
Roedy> kludge.

Likewise, otherwise the API is going to get hopelessly
spammed up. My feeling is that there is no plan however. Certainly
they have not told everyone if they have.

Phil

Phillip Lord

unread,
Jun 7, 2001, 7:01:08 AM6/7/01
to
>>>>> "Glenn" == Glenn G D'mello <dev...@dmello.org> writes:

Glenn> Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote in
Glenn> news:vfd78hj...@cs.man.ac.uk:

Glenn> <<Snip>>

>> them. I agree that it would be nice to have a cleaner system than
>> this. However sacrificing backwards compatibility is not going to
>> happen. Under the circumstances I would rather than a reasonable
>> if

Glenn> Hasn't this already happened with 1.2? (witness the -target
Glenn> command line option to javac)! So, maybe 1.5 should 'do the
Glenn> right thing' by default with an option for backward
Glenn> compatibility to be used where required.

Glenn> Hmm. I'm begining to really like this idea... :)

Backwards compatibility is available from the 1.2
compiler though.

This is fairly similar to the AWT event model. As
far as I know 1.2 (and 1.3 and 1.4) still support the 1.0 event model,
in parallel to the 1.1 model.

I agree that this is a little nuts but there you have
it.

Phil

Phillip Lord

unread,
Jun 7, 2001, 7:08:03 AM6/7/01
to
>>>>> "Jorn" == Jorn W Janneck <jan...@NOSPAM-eecs.berkeley.edu> writes:

>> I am not sure that this is true. Paramaterised typing is a
>> fairly old technology and reasonably well understood, and not
>> that hard to teach. Certainly there is experience in teaching it.

Jorn> but my point was not that parametric types are the issue, but
Jorn> rather that the rules governing their use due to the
Jorn> awkwardnesses of the current proposal, and complicate the
Jorn> matter considerably.

You might be right, although as I have not taught
generics yet I don't really know. My own feeling is that using
generics in a simple manner should be possible. Its is certainly the
case that in some circumstances the use of generics is rather clunky
due to the underlying implementation. Still some of these have gone
(the method used for instantiating a generically typed array for
instance) when compared to GJ.

>> Also I think that its most likely that beginners will be
>> instantiating classes which are parameterised, rather than
>> creating them, so its less of a problem.

Jorn> the issue i raised concerned the *use* of parametric classes,
Jorn> rather than their creation.

As far as I can see whilst using parametric classes
there should be relatively few unchecked warnings produced. Again as
well as not having taught Java generics yet, I have not used them in
anger, so I can't say for sure.


>> Under the circumstances I would rather than a reasonable
>> if slightly messy genericity system, than none at all.

Jorn> i disagree. so did sun already once.


Did they?

Phil

Mats Olsson

unread,
Jun 7, 2001, 7:09:55 AM6/7/01
to
In article <t3knf9...@10.0.0.2>, <Bart.Van...@nowhere.be> wrote:
>Mats Olsson <ma...@dtek.chalmers.se> wrote:
>> If I write a class that takes List<Integer> as an argument and hand
>> the .class file to you, you can ignore generics completly and just call
>> it with a List object, without bothering even to cast it to a parameterized
>> type. At least if you are using a non-generics compiler... it won't look
>> at the .class file section that details the generics info.
>
>What happens when you pass a List that contains more than just Integers?
>Failed casts at runtime?

ClassCast exception at the point of extraction, yes. So as long as you
don't extract them, you don't even know you have a problem.

>I don't see this as an advantage of the current proposal actually.

Well, it does allow you to rewrite the current Collection classes
as generic classes, without breaking any of the current code and without
modifiying the JVM's.

Achiving that kind of backwards compatibility if generic classes
was first class types is more complex, but still doable - basically, the
JVM would need to accept that a List [1] in an 1.4 or older .class file
would be implicitly castable to any List<T>.

/Mats

[1] not just List, of course - any generic type.

Phillip Lord

unread,
Jun 7, 2001, 7:16:35 AM6/7/01
to
>>>>> "Roedy" == Roedy Green <ro...@mindprod.com> writes:

Roedy> On Thu, 07 Jun 2001 01:12:14 +0200, Artur Biesiadowski
Roedy> <ab...@pg.gda.pl> wrote or quoted :

>> There is one additional benefit on gj approach. You can ignore it
>> entirely, DO NOT use generics in proposed way and interface to
>> code which uses generics, still without having to use them.

Roedy> Could you expound on that with an example?


Its fairly straightforward.

If you have a generic library then you can use it
non generically very simply. You just address the parameterised types
as their erasures. So


public void push( A a );

public A pop();


where A is parameterised type extending Object

can also be addressed as

public void push( Object a );

public Object pop();


It is also possible to use a non generic library generically.
They have a tool which operates on non generic code and reverse
engineers in the generics. Obviously the code inside the library is
non generic so can't be type checked, but the interface then does
become generic. The point is that you don't need the source for
this. It works straight on the class files.

I can't remember the details of how this works. So for
instance take...

void put( Object key, Object value );
Object get( Object key );


given that ...

void put( A key, B value )


its not clear whether get should be parameterised
as
B get( A key );

or

A get( B key );

At least not to the computer. There was some mechanisms
for sorting this out though. In the GJ paper they claimed that they
only had to modify one or two classes in the Collections API, and that
the rest could be parameterised automatically.


Phil

Phillip Lord

unread,
Jun 7, 2001, 7:20:37 AM6/7/01
to

>>>>> "Mats" == Mats Olsson <ma...@dtek.chalmers.se> writes:

Mats> So, now we won't be able to write correct programs that
Mats> requires the use of these casts cleanly... _not_ a win from
Mats> where I'm standing... and there will be lots of programs that
Mats> requires it. Consider any program using serialization, for
Mats> example.

Mats> // the following will give you a warning. Even though
Mats> there is no // other bloody way of writing this code.
Mats> List<Integer> intList = (List<Integer>)
Mats> objectInputStream.readObject();

Mats> Not a good solution. Also, any use of serialization means
Mats> that you can export data and shovel it around (using RMI for
Mats> example), all looking nice and typesafe until you find an
Mats> Integer in your List<String>.


This is a problem with the API though. Serialisation can be
considered to be a container like anything else. Using genericity you
would only get objects of a single type (or addressed as a single
super type) out of a single Stream. In the same way mixing objects
types in a single Vector, or Hash would not be (is not!) a good idea.

In the case of Vectors this is not too much of a problem, but
I don't think it maps as well into the serialisation API, which would
require changing.

Phil

Phillip Lord

unread,
Jun 7, 2001, 7:23:09 AM6/7/01
to
>>>>> "Bart" == Bart Vanhauwaert <Bart.Van...@nowhere.be> writes:

Bart> Les Stroud <les_s...@hotmail.com> wrote:
>> I certainly see your point. I am an OO biggot. Generics
>> typically lead to larger binaries and unmaintainable code. They
>> definitely don't

Bart> Generics certainly lead to bigger binaries although that's
Bart> only a problem in the embedded world.


This is not generically (!) true. Generics do not always
lead to bigger binaries. They may do so in C++ but there again C++ has
a thoroughly knackered type system. The proposal for Java would not
result in bigger binaries (or at only of the order of a few bytes per
class, per method).

Phil

Roger L. Cauvin

unread,
Jun 7, 2001, 8:02:56 AM6/7/01
to
"Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
news:9fmidk$f9d$1...@nyheter.chalmers.se...

>
> List l = new List<Integer>(); // warning here
> l.add("a string"); // no warning
> List<Integer> l2 = (List<Integer>) l;
> List<String> l3 = (List<String>) l; // well, why not?
> String s = l3.get(0); // works real nice
> Integer i = l2.get(0); // crash here
>
> Object[] a = new Integer[10];
> a[0] = "a string"; // crash here
> Integer[] b = (Integer[]) a;

By "crash here", what do you mean? Will the runtime raise a
ClassCastException?

--
Roger L. Cauvin
rca...@homemail.com
http://lightning.prohosting.com/~rcauvin

Roger L. Cauvin

unread,
Jun 7, 2001, 8:16:42 AM6/7/01
to

"Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
news:9fmf68$f4k$1...@nyheter.chalmers.se...

>
> The proposed Java generics is much less complex and less
> powerful, only adding type-safety at compile time and only for
> objects, not primitive values.

How does Java generics handle the following case:

List<Integer> sl = new ArrayList<String>();
sl.add("hello");

Does the compiler flag complain about attempting to add a string to a list
of integers?

Artur Biesiadowski

unread,
Jun 7, 2001, 10:34:58 AM6/7/01
to

"Roger L. Cauvin" wrote:
>
> "Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
> news:9fmf68$f4k$1...@nyheter.chalmers.se...
> >
> > The proposed Java generics is much less complex and less
> > powerful, only adding type-safety at compile time and only for
> > objects, not primitive values.
>
> How does Java generics handle the following case:
>
> List<Integer> sl = new ArrayList<String>();
> sl.add("hello");
>
> Does the compiler flag complain about attempting to add a string to a list
> of integers?

I think it would generate error. You would need to do

List<Integer> sl = (List<Integer>)new ArrayList<String>();

but it is about same legal as

Integer i = (Integer)new String("aaa");


Artur

Mats Olsson

unread,
Jun 7, 2001, 10:56:01 AM6/7/01
to
In article <9fnqe7$54l42$1...@ID-20080.news.dfncis.de>,

Roger L. Cauvin <rca...@homemail.com> wrote:
>"Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
>news:9fmidk$f9d$1...@nyheter.chalmers.se...
>>
>> List l = new List<Integer>(); // warning here
>> l.add("a string"); // no warning
>> List<Integer> l2 = (List<Integer>) l;
>> List<String> l3 = (List<String>) l; // well, why not?
>> String s = l3.get(0); // works real nice
>> Integer i = l2.get(0); // crash here
>>
>> Object[] a = new Integer[10];
>> a[0] = "a string"; // crash here
>> Integer[] b = (Integer[]) a;
>
>By "crash here", what do you mean? Will the runtime raise a
>ClassCastException?

Yes.

/Mats

Mats Olsson

unread,
Jun 7, 2001, 11:01:56 AM6/7/01
to
In article <3B1F9112...@pg.gda.pl>,

Artur Biesiadowski <ab...@pg.gda.pl> wrote:
>
>
>"Roger L. Cauvin" wrote:
>>
>> "Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
>> news:9fmf68$f4k$1...@nyheter.chalmers.se...
>> >
>> > The proposed Java generics is much less complex and less
>> > powerful, only adding type-safety at compile time and only for
>> > objects, not primitive values.
>>
>> How does Java generics handle the following case:
>>
>> List<Integer> sl = new ArrayList<String>();
>> sl.add("hello");
>>
>> Does the compiler flag complain about attempting to add a string to a list
>> of integers?
>
>I think it would generate error. You would need to do
>
>List<Integer> sl = (List<Integer>)new ArrayList<String>();

Won't help. This is statically checkable, and as a String isn't a
subclass of Integer, it won't compile.

However,

List<Integer> sl = (List<Integer>) ((List) (new ArrayList<String>()));

... would compile (with a warning) and run fine - as a container for
Integers, of course.

/Mats

Phillip Lord

unread,
Jun 7, 2001, 11:26:23 AM6/7/01
to
>>>>> "Bart" == Bart Vanhauwaert <Bart.Van...@nowhere.be> writes:

Bart> Mats Olsson <ma...@dtek.chalmers.se> wrote:
>> If I write a class that takes List<Integer> as an argument and
>> hand the .class file to you, you can ignore generics completly
>> and just call it with a List object, without bothering even to
>> cast it to a parameterized type. At least if you are using a
>> non-generics compiler... it won't look at the .class file section
>> that details the generics info.

Bart> What happens when you pass a List that contains more than just
Bart> Integers? Failed casts at runtime?

No. If you dealing with a legacy library which has not been
parameterised then its got to cope with mixed lists anyway.

If you have a parameterised class then I don't think
that you can parameterise over a parameterised type (ie you can't
instantiate an object as new Blah<List<Integer>>, although I could be
wrong about this.

Bart> I don't see this as an advantage of the current proposal
Bart> actually.

You do get a additional compile time safety. Not all the time
but some of it at least.

Phil

Phillip Lord

unread,
Jun 7, 2001, 11:27:59 AM6/7/01
to
>>>>> "Roger" == Roger L Cauvin <rca...@homemail.com> writes:

Roger> "Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
Roger> news:9fmf68$f4k$1...@nyheter.chalmers.se...


>> The proposed Java generics is much less complex and less
>> powerful, only adding type-safety at compile time and only for
>> objects, not primitive values.

Roger> How does Java generics handle the following case:

Roger> List<Integer> sl = new ArrayList<String>();
Roger> sl.add("hello");

Roger> Does the compiler flag complain about attempting to add a
Roger> string to a list of integers?

Its a compile error.


ArrayList<String> is not a subtype of List<Integer>
so you its an invalid assignment.

Phil

Chris Smith

unread,
Jun 7, 2001, 12:48:07 PM6/7/01
to
"Mats Olsson" <ma...@dtek.chalmers.se> wrote ...

> List l = new List<Integer>(); // warning here
> l.add("a string"); // no warning
> List<Integer> l2 = (List<Integer>) l;
> List<String> l3 = (List<String>) l; // well, why not?
> String s = l3.get(0); // works real nice
> Integer i = l2.get(0); // crash here

So, essentially, the generics proposal has these effects:

1. Prevents clean compiles in ways that can't be worked around.
2. Removes cast syntax *without* removing the corresponding dangers.
3. Provides no additional type safety; only the illusion of it.

I'm not sure I ike how this looks.

Chris Smith

Phillip Lord

unread,
Jun 7, 2001, 1:11:15 PM6/7/01
to
>>>>> "Chris" == Chris Smith <cds...@twu.net> writes:

Chris> "Mats Olsson" <ma...@dtek.chalmers.se> wrote ...


>> List l = new List<Integer>(); // warning here l.add("a string");
>> // no warning List<Integer> l2 = (List<Integer>) l; List<String>
>> l3 = (List<String>) l; // well, why not? String s = l3.get(0);
>> // works real nice Integer i = l2.get(0); // crash here

Chris> So, essentially, the generics proposal has these effects:

Chris> 1. Prevents clean compiles in ways that can't be worked
Chris> around. 2. Removes cast syntax *without* removing the
Chris> corresponding dangers. 3. Provides no additional type
Chris> safety; only the illusion of it.

Chris> I'm not sure I ike how this looks.


Have you read the generics proposal?

The generics proposal does not remove the cast
syntax. Ideally it would remove the cast syntax, but it can't for many
reasons of legacy. Combining casting with genericity is going to be
dangerous but as far as I can see no more dangerous than casting is
per se.

There are some circumstances where it can affect
clean compiles indeed yes, although only warnings will be emitted and
these can of course be switched off. The same is true of
deprecation. How common this will be in practise remains to be
seen. Like deprecation though probably not as often as you might
expect, as they will generally only occur when you are writing
parametric classes not when you are using them.

And as for the last point I am confused as to how you
can have an illusion of type safety. When correctly implemented types
are little more than an illusion anyway. The point of them it too
allow the compiler to tell you things. The genericity proposal allows
the compiler to tell you more things than before, and therefore it is
sensible.

Phil


Roedy Green

unread,
Jun 7, 2001, 4:39:41 PM6/7/01
to
On 07 Jun 2001 12:23:09 +0100, Phillip Lord <p.l...@hgmp.mrc.ac.uk>
wrote or quoted :

> Generics do not always
>lead to bigger binaries. They may do so in C++ but there again C++ has
>a thoroughly knackered type system.

In which languages are you familiar with how generics work under the
hood? Which of these do you think got it most right? Which do you
think would be the best model for Java, given any boxes Java has
already got itself into with upward compatibility?

Roedy Green

unread,
Jun 7, 2001, 4:40:43 PM6/7/01
to
On Thu, 07 Jun 2001 20:39:41 GMT, Roedy Green <ro...@mindprod.com>
wrote or quoted :

>In which languages are you familiar with how generics work under the
>hood? Which of these do you think got it most right? Which do you
>think would be the best model for Java, given any boxes Java has
>already got itself into with upward compatibility?

This question is for anyone, not just for Phil.

Mats Olsson

unread,
Jun 7, 2001, 5:10:01 PM6/7/01
to
In article <vfofs0i...@cs.man.ac.uk>,

Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote:
>>>>>> "Bart" == Bart Vanhauwaert <Bart.Van...@nowhere.be> writes:
>
> Bart> Mats Olsson <ma...@dtek.chalmers.se> wrote:
> >> If I write a class that takes List<Integer> as an argument and
> >> hand the .class file to you, you can ignore generics completly
> >> and just call it with a List object, without bothering even to
> >> cast it to a parameterized type. At least if you are using a
> >> non-generics compiler... it won't look at the .class file section
> >> that details the generics info.
>
> Bart> What happens when you pass a List that contains more than just
> Bart> Integers? Failed casts at runtime?
>
> No. If you dealing with a legacy library which has not been
>parameterised then its got to cope with mixed lists anyway.

It's the other way around. Running code written for 1.4 or earlier
on the 1.5 class library after its APIs have been rewritten to use
generics will be possible without needing to modify the 1.5 JVM. In
fact, you can run the 1.5 class lib on a 1.4 JVM, IIUC.

> If you have a parameterised class then I don't think
>that you can parameterise over a parameterised type (ie you can't
>instantiate an object as new Blah<List<Integer>>, although I could be
>wrong about this.

You are, fortunately. Something you can't do however is

class A<T> extends T {
}

... or at least I can't see how you can do this using type erasure.

/Mats

Roger L. Cauvin

unread,
Jun 7, 2001, 6:45:38 PM6/7/01
to
"Phillip Lord" <p.l...@hgmp.mrc.ac.uk> wrote in message
news:vfiti8i...@cs.man.ac.uk...

>
> Roger> How does Java generics handle the following case:
>
> Roger> List<Integer> sl = new ArrayList<String>();
> Roger> sl.add("hello");
>
> Roger> Does the compiler flag complain about attempting to
> Roger> add a string to a list of integers?

>
> Its a compile error.
>
> ArrayList<String> is not a subtype of List<Integer>
> so you its an invalid assignment.

Oops. What I meant was:

List<Integer> sl = new ArrayList<Integer>();
sl.add("hello");

Which kinds of warnings and errors should the compiler produce for this
code?

Jorn W Janneck

unread,
Jun 7, 2001, 6:46:20 PM6/7/01
to

"Roedy Green" <ro...@mindprod.com> wrote in message
news:tfpvht8ju51gomvlm...@4ax.com...

> On 07 Jun 2001 12:23:09 +0100, Phillip Lord <p.l...@hgmp.mrc.ac.uk>
> wrote or quoted :
>
> > Generics do not always
> >lead to bigger binaries. They may do so in C++ but there again C++ has
> >a thoroughly knackered type system.
>
> In which languages are you familiar with how generics work under the
> hood? Which of these do you think got it most right? Which do you
> think would be the best model for Java, given any boxes Java has
> already got itself into with upward compatibility?

eiffel. (minus covariance.)

polyj is a nice model for how this can be done in java, though i am not so
crazy about the signature constraints.

i also like the way type construction works in haskell, but this is probably
not a good model for the java context.

cheers,

-- j

Matt Kennel

unread,
Jun 7, 2001, 6:53:54 PM6/7/01
to
Bart.Van...@nowhere.be <Bart.Van...@nowhere.be> wrote:

:Les Stroud <les_s...@hotmail.com> wrote:
:> I certainly see your point. I am an OO biggot. Generics typically
:> lead to larger binaries and unmaintainable code. They definitely don't
:
:Generics certainly lead to bigger binaries although that's only a problem
:in the embedded world. (Hands up any of you who have inherited from
:a standard collection just to avoid the typecasts and be sure of what's
:in a certain collection at runtime. I know I have and thus I know the
:bloat is (partly) already there in my programs.)

With appropriate compiler technology generics don't cause much bloat---
if you don't need arbitrary dynamic loading of new classes that
might possibly call any feature in parameterized classes.

Free Sather and Eiffel compilers do some dataflow analysis to find the
transitive closure of all possible routines that might be called in
the program with the parameterization as actually used and
specialized. This means that the library designer could write a very
heavy and full-featured generic class and when the user wants just
one or two specializations and only uses the most elementary features
of them, only the code for those features was ever generated.

This strategy is highly effective; generics in Eiffel and Sather
make much less bloat than in typical C++ implementations and yet
are often have fully specialized new code generated for each type
instantiation for maximum speed.

:But I find e.g. generic collections much clearer than their type-amorf


:variants with the associated type-cast hell.
:
:> make sense in the enterprise environment where the model is more
:> important than the implementation.
:
:I think this statement is based on personal preference and not on
:facts.
:
:> However, the adding of generics will allow java to approach the more
:> computational intense applications found in scientific and enginering.
:
:No, it wont because the proposed addition to the standard doesn't
:allow non-class types as type parameters for generic classes.

Argh double argh.

Well actually I think that things like integers, floating point
numbers and complex versions thereof really should be instances of
classes, but they should NOT be accessed by reference variables, but
by 'value' variables. Why should 'class' be isomorphic to
'only accessible by references that can be aliased'?

Yet another example where Java screws the pooch compared to
its superior ancestors.

:A big flaw indeed, but understandable, given the design decisions
:of generic java.

:> Specifically, if you can acheive polymorphism around primitives then
:> you can employ some interesting compiler (jit not javac) optimizations
:> that will rival C++ and even Fortran in some instances. The overhead
:
:See http://oonumerics.org/blitz for more examples of what generic
:programming can do for numerical applications.

--
* Matthew B. Kennel/Institute for Nonlinear Science, UCSD
*
* "To chill, or to pop a cap in my dome, whoomp! there it is."
* Hamlet, Fresh Prince of Denmark.

Mats Olsson

unread,
Jun 7, 2001, 7:05:19 PM6/7/01
to
In article <9fp037$5eg2r$1...@ID-20080.news.dfncis.de>,

Roger L. Cauvin <rca...@homemail.com> wrote:
>"Phillip Lord" <p.l...@hgmp.mrc.ac.uk> wrote in message
>news:vfiti8i...@cs.man.ac.uk...
>>
>> Roger> How does Java generics handle the following case:
>>
>> Roger> List<Integer> sl = new ArrayList<String>();
>> Roger> sl.add("hello");
>>
>> Roger> Does the compiler flag complain about attempting to
>> Roger> add a string to a list of integers?
>>
>> Its a compile error.
>>
>> ArrayList<String> is not a subtype of List<Integer>
>> so you its an invalid assignment.
>
>Oops. What I meant was:
>
> List<Integer> sl = new ArrayList<Integer>();
> sl.add("hello");
>
>Which kinds of warnings and errors should the compiler produce for this
>code?

Nothing. This is where the generics proposal works. You can even do

List<Number> list = new ArrayList<Integer>();

if you like.

/Mats

Jon Skeet

unread,
Jun 7, 2001, 7:57:37 PM6/7/01
to
Roger L. Cauvin <rca...@homemail.com> wrote:

> Oops. What I meant was:
>
> List<Integer> sl = new ArrayList<Integer>();
> sl.add("hello");
>
> Which kinds of warnings and errors should the compiler produce for this
> code?

It should (and does) produce an error:

Test.java:8: cannot resolve symbol
symbol : method add (java.lang.String)
location: interface java.util.List<java.lang.Integer>
sl.add("hello");
^

--
Jon Skeet - <sk...@pobox.com>
http://www.pobox.com/~skeet/
If replying to the group, please do not mail me too

Jon Skeet

unread,
Jun 7, 2001, 7:59:19 PM6/7/01
to
Mats Olsson <ma...@dtek.chalmers.se> wrote:

> > List<Integer> sl = new ArrayList<Integer>();
> > sl.add("hello");
> >
> >Which kinds of warnings and errors should the compiler produce for this
> >code?
>
> Nothing. This is where the generics proposal works. You can even do

I think you may have misread the example - you can't add a String to a
List of Integers.

Mats Olsson

unread,
Jun 7, 2001, 8:02:49 PM6/7/01
to
In article <MPG.158a25b3f...@mrmog.peramon.com>,

Jon Skeet <sk...@pobox.com> wrote:
>Mats Olsson <ma...@dtek.chalmers.se> wrote:
>
>> > List<Integer> sl = new ArrayList<Integer>();
>> > sl.add("hello");
>> >
>> >Which kinds of warnings and errors should the compiler produce for this
>> >code?
>>
>> Nothing. This is where the generics proposal works. You can even do
>
>I think you may have misread the example - you can't add a String to a
>List of Integers.

*blush* - oops. In my defense, I'll claim the question was too easy :-)

/Mats

Roger L. Cauvin

unread,
Jun 7, 2001, 8:08:07 PM6/7/01
to
"Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
news:9fp1bf$mqv$1...@nyheter.chalmers.se...

Doesn't the compiler choke on the call to the add() method?

cppwiz

unread,
Jun 7, 2001, 9:37:23 PM6/7/01
to
[Please note that I have trimmed headers as this is specifically a C++
templates
versus Java templates post]

"Artur Biesiadowski" <ab...@pg.gda.pl> wrote in message
news:3B1E1EE0...@pg.gda.pl...

>
> I see your points, but you forget to mention one thing. If we would
> choose your way (separate class for every type) we would end up with
> very bloated runtime...

...Only if template class designers wanted it so.

Your argument about C++ templates being bloated is flawed.

C++ templates give a programmer precise control over the class.

It is trivial to write bloat proof template containers in C++
that *match* the semantics of Java containers (pure reference semantics,
no ownership).

[ example:
One would create an implementation container that dealt strictly
with void *. Then an "outer" container would wrap the implementation
and would only use template arguments in cast expressions, which
would disappear at compile time. In this way, identical code would
be re-used (the implementation class) for different container
element types. No bloat.

We can be more specific.
One may preserve value semantics and suppress
most of the bloat in containers by using a similar strategy, yet
require the duplication of about 4 functions (default constructor,
copy constructor, copy assignment operator and destructor).

It should be noted that the added cost of these
strategies is loss of speed in C++, For Java the speed
loss is built in. This speed loss is inherent in reference
semantics (the additional pointer load cost).]

If anything, it is Java templates implemented through Object
that are bloated. Any object that plugs into Java generics
needs to be derived from Object, which imposes storage
overhead on such a derived class objects. In Java, you already pay
for that overhead without templates so it seems like a good
idea to maximize the use of Object, but the bloat is still there,
despite the fact that it is gratuitous.

I was initially excited about the possibility of using templates in Java
as an alternative to C++ (despite my namesake I do spend time looking
for better languages) however Java templates fell short of the mark.
The problem would not be as bad, if int and company been granted
class status *from the start*.

Out of curiosity how does one write a generic container
with value semantics (see example 1) in Java that exercises
ownership over its elements ?

Some of the recent talk of garbage collection made me do some thinking
about just how weak a promise GC is in Java.

In C++ it is easily possible (with no exaggeration) to write
programs that never explicitly use new/delete. One can rely
entirely on C++ containers. It is true that the C++ containers
do not have 100% coverage for every possible ADT, however
it is pretty close. Additionally some ADT's may be represented
as a composition of 2 or more containers.

The point is, its not hard at all to write a C++ program
that has automated memory management. The guarantee
that C++ makes for such a program is stronger than
what a Java program can guarantee.

example 1

#include <vector>

void f (int i)
{
vector< int > vec;
vec.push_back (i);
vec.push_back (10);
}

int main ()
{
int i;
initialize_i (i);
f (i);
g (i); // some other function
/* do rest of program */
}

Trivial example, but can you get such hands-free memory management in Java ?

In C++ you can use (or engineer) classes that are smart enough
to manage memory. These classes prove to be
higher level than Java garbage collection which only
tracks a single resource (memory). Additionally Java
has the error prone requirement that programmers
must set references to null.

In C one not free'ing or an additional free may confound you.

In Java one less reference set to null may confound you.

C++ pushes the complexity into a standard class,
and lets it manage the problem, just select the right container and go.

The real innovation of "Java technology" is the portability concept (VM),
and its broad and rich libraries.
The language itself is weak. the garbage collection that Java programmers
seem to think make
their code magically safe is in fact prone to programmer error, and only
addresses only a single kind
of resource (what about sockets ? what about file handles ? etc..).

There is an *abundance* of misinformation circulating through c.l.j.a.

The C++ template bloat myth is one.

Somewhere, in another thread the notion arose that typical C++
derived class object layout strategy (contiguous) was slow.

I see claims that stack allocation is thought to be equivalent
to heap allocation in terms of speed. rubbish.

These myths are erroneous arguments used to discredit C++.

Don't believe everything you read (*especially* in c.l.j.a.) and then
mindlessly parrot it.

Matt Kennel

unread,
Jun 7, 2001, 9:50:48 PM6/7/01
to
On Thu, 7 Jun 2001 21:37:23 -0400, cppwiz <cpp...@prodigy.net> wrote:
:[Please note that I have trimmed headers as this is specifically a C++

In other words you have to engage in some semi-perversions to use a
non-template class with (void*) aka Object instead of writing a
straight forward generic container like what you really want.

Like suppose *shock* you want to call methods off of the pointers
that are declared (void *) in your grungy internal implementation?

What if you are parameterizing over two different types T1 and T2?
Will your void * laden intermediate representation use it for
both interchangably?

:If anything, it is Java templates implemented through Object


:that are bloated. Any object that plugs into Java generics
:needs to be derived from Object, which imposes storage
:overhead on such a derived class objects. In Java, you already pay
:for that overhead without templates so it seems like a good
:idea to maximize the use of Object, but the bloat is still there,
:despite the fact that it is gratuitous.

Well there is data bloat and there is parameterized code bloat.

I am not defending Java for its egregious lack of value classes.

: I was initially excited about the possibility of using templates in Java

and suppose in f you assigned a globally available pointer
vec2 to vec?

:In C++ you can use (or engineer) classes that are smart enough
:to manage memory.

Unless you make aliases which is precisely problem that global garbage
collection solves that isolated local per-class schemes insensitive
to global dataflow and assignment of references cannot solve.

:These classes prove to be


:higher level than Java garbage collection which only
:tracks a single resource (memory).

:Additionally Java
:has the error prone requirement that programmers
:must set references to null.

Well a local variable going out of scope, just as in C++, means that
its reference is no longer live and will not result in retained
memory. I see little difference.

:In C one not free'ing or an additional free may confound you.

Of course it could if another live reference still needs it!!!

:In Java one less reference set to null may confound you.

Keep memory around for longer than necessary, but not cause crashes.

:The real innovation of "Java technology" is the portability concept (VM),


:and its broad and rich libraries.
:The language itself is weak. the garbage collection that Java programmers
:seem to think make
:their code magically safe is in fact prone to programmer error, and only
:addresses only a single kind
:of resource (what about sockets ? what about file handles ? etc..).

Garbage collection is a global algorithm to solve one single, difficult
and common problem. It does not solve world piece and situations
where you need defined synchronous finalization.

Note that 'malloc' and its moral equivalents were once considered
"automatic" memory management as compared to link-time allocation of
raw fixed blocks of core memory divvied up at a low level by the
program.

malloc does not solve world piece or socket management either.

:There is an *abundance* of misinformation circulating through c.l.j.a.


:
:The C++ template bloat myth is one.

By your example the "you can fix C++ but only by massive perversions
and virtuoso hacking" myth appears to be true. Also look at source
code for a STL implementation as compared to, e.g. an Eiffel library.

:Somewhere, in another thread the notion arose that typical C++


:derived class object layout strategy (contiguous) was slow.
:
:I see claims that stack allocation is thought to be equivalent
:to heap allocation in terms of speed. rubbish.

Oddly enough these are often backed up by empirical testing and
published in journals. Of course the GC's are usually high-quality
ones as in Smalltalk and Lisp and not Java implementations.

It is true that high-water mark of memory foot print is larger
with GC than manual deallocation techniques.

I personally believe in manually worrying about the Big Stuff or
the Frequently Allocated Stuff and then letting the GC take care of
the rest.

In my own experience with GC I was once convinced that by making some
optimizations to save allocated objects between calls, nullify
pointers religiously and do some manual freeing I would gain some
speed. Even though I only targeted those areas where I was "sure" it
would pay off the empirical performance improvement was insignificant.

After experiencing that a few times I learned to stop worrying and
love Garbage Collection, it's the Bomb.

:These myths are erroneous arguments used to discredit C++.


:
:Don't believe everything you read (*especially* in c.l.j.a.) and then
:mindlessly parrot it.

cppwiz

unread,
Jun 8, 2001, 1:05:10 AM6/8/01
to

"Matt Kennel" <SPAMBGONEmbke...@yahoo.com> wrote in message
news:slrn9i0brn.o8i.SPAMB...@lyapunov.ucsd.edu...

Refering to C and C++ objects through a void pointer is about as arbitrary
as
refering to java objects through Object reference.

True, void * can be dangerous in certain contexts but I don't believe that
this
is one of them because as you will see there is a localized, one-to-one
mapping
between pointer to T (the template argument) and pointer to void.

The library implementor may make errors, but we can make the same assumption
of
any library code, in any language. java.String may have a bug in it, in a
particular
implementation but this is orthagonal (to use a term that has been getting
thrown
about a bit lately :D) to the quality of its interface.

> Like suppose *shock* you want to call methods off of the pointers
> that are declared (void *) in your grungy internal implementation?

As pointers can't have members I am going to assume you mean

"suppose I want to call the member function of an element stored in the
container"

Not a problem, see example.

the outer container in my generic idea can return reference to
objects or pointers to objects of a certain type. (the choice of ref/ptr is
in
the hands of the designer of course). Type safety is ensured.

Its really not that hard Matt. I am explicitly doing what a java
implementation would do to behind the scenes, and using the
C++ pointer to void *kind of* like the Java reference to Object.

The nice thing about the C++ implementation is that it can
support primative types.

I will write a template container class that uses the bloat-proof
strategy I outline. It has very limited functionality and I omit error
checking
because I don't have time to write a full blown implementation :)

#include <stack>
#include <iostream>

template <typename T> class Stack
{
private:
std::stack<void *> impl;
public:
void push (T *p) { impl.push (p); }
void pop () { impl.pop (); }
T *top () { return (T*) impl.top (); }
};

struct A
{
int data;
A (int val) : data (val) {}
public:
void f ()
{
std::cout << data << std::endl;
}
};

int main ()
{
A a1(1), a2(2);

Stack<A> thestack;

thestack.push (&a1);
thestack.push (&a2);
thestack.top ()->f();
thestack.pop ();
thestack.top ()->f();
thestack.pop ();
}

Now for those who may think that Stack does
have overhead in the form of its public interface please note
a few things:

1) the public interface is inline. A sane compiler would expand
the function body (AKA the real call) at the point of the outer call.

2) the C++ cast (T*) will not exist at runtime, it is a compile time
construct.

3) Note that for any set of template arguments given to Stack
only one version of std::stack<void*> needs to be generated.

I think its kind of cool :)

This is a very simplistic example. Think of it as a proof of concept.
My claim was that I could implement a bloat proof container
in C++ and I did. I did not claim that It would be a suitable
replacement for either Java's or C++'s standard containers
in the 5 minutes it took me to write it.

So comparisons of its usefulness against containers
that were engineered by teams of developers with
more than 5 minutes to spare, or weaknesses
related to its immaturity will not be acknowledged :)

Just use your imagination, it should not be hard to
see how Stack can be advanced, and the same concepts
applied to other ADT classes.

Although my Stack class was written quickly, if it was
intended for serious re-use I would not burden the
user (programmer) to use raw pointers but instead use a smart
pointer class type, or let reference type be the outer type passed
and returned... there are so many options... its hard to consider
then all in this spur of the moment response.

As far as smart pointers go there are alternatives that fall within the
realm of legal C++, and nearly within the realm of standard C++.
(www.boost.org).

> What if you are parameterizing over two different types T1 and T2?
> Will your void * laden intermediate representation use it for

> both interchangeably?

T1, and T2 would be distinct types if the template class user wanted it so.

I don't think I understand what you are getting at, You have to be more
specific.

what do you want to achieve ? And in that case, what do you perceive
as a limitation C++ templates ?


Mats Olsson

unread,
Jun 8, 2001, 4:24:06 AM6/8/01
to
In article <9fplq4$69h6$1...@newssvr06-en0.news.prodigy.com>,
cppwiz <cpp...@prodigy.net> wrote:

*snip*

>I will write a template container class that uses the bloat-proof
>strategy I outline. It has very limited functionality and I omit error
>checking
>because I don't have time to write a full blown implementation :)
>
>#include <stack>
>#include <iostream>
>
>template <typename T> class Stack
> {
> private:
> std::stack<void *> impl;
> public:
> void push (T *p) { impl.push (p); }
> void pop () { impl.pop (); }
> T *top () { return (T*) impl.top (); }
> };
>

>I think its kind of cool :)

Yea. It's in fact a standard C++ idiom to avoid template bloat. I
first read it in Coplien, "Advanced C++ Programming Styles and Idioms", 1992.

/Mats

Jorn W Janneck

unread,
Jun 8, 2001, 5:49:43 AM6/8/01
to

"Mats Olsson" <ma...@dtek.chalmers.se> wrote in message
news:9fq236$o6o$1...@nyheter.chalmers.se...

okay, but what in the world is *nice* or 'cool' about this simply eludes me.
personally, i see not a big difference in hacking the type system from the
outside (of a generic class) or the inside. sure, you can reuse the hacks
this way, and they are encapsulated, but they are still hacks.

if the class you were writing was significantly bigger than a toy stack,
involved maybe more than one generic argument, and bounded its arguments,
then this little technique would very soon reach its limits. not to speak of
maybe exposing some of the internal state to derived classes by making it
protected or some such.

so i read this technique as an elaborate way of working around a shortcoming
of the c++ type system and its typical implementations. no doubt these will
develop for the stuff that is currently suggested for java, too. and no
doubt that in five years time, people will post that they actually *like*
them.

it's sad to see so much time and attention and energy being wasted on this
stuff. if c++ has proper generic types, this junk would not be necessary. if
java gets them, stuff like that would not have to happen. i see the reasons
for the c++ design (and even, grudgingly, agree with them), but i do not
quite see them in the java case.

best regards,

-- j


Bart.Van...@nowhere.be

unread,
Jun 8, 2001, 5:15:51 AM6/8/01
to
Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote:
> Bart> What happens when you pass a List that contains more than just
> Bart> Integers? Failed casts at runtime?
> No. If you dealing with a legacy library which has not been
> parameterised then its got to cope with mixed lists anyway.

Indeed. But basically the other way around you can have problems?
Ie. an old style class passing a mixed List to a new style class
expecting a List<Integer>. Or is there some mechanism to prevent
this? And is there a mechanisme to prevent one class passing a
List<Integer> to another expecting a List<MyType> for example?

> If you have a parameterised class then I don't think
> that you can parameterise over a parameterised type (ie you can't
> instantiate an object as new Blah<List<Integer>>, although I could be
> wrong about this.

That would also be a pity.

> Bart> I don't see this as an advantage of the current proposal
> Bart> actually.
> You do get a additional compile time safety. Not all the time
> but some of it at least.

This is a mixed blessing. On the other hand I see why this decision has
been taken.

cu bart

--
http://www.irule.be/bvh/

Bart.Van...@nowhere.be

unread,
Jun 8, 2001, 6:01:26 AM6/8/01
to
Matt Kennel <SPAMBGONEmbke...@yahoo.com> wrote:
> In other words you have to engage in some semi-perversions to use a
> non-template class with (void*) aka Object instead of writing a
> straight forward generic container like what you really want.

Actually, no. I guess the original poster was describing so
called template specialization.

To fully understand the concept, you should be familiar with
C++ templates but I'll let Stroustrup explain what it is. From
13.5 Specialization, The C++ programming language, 3th ed.

<start quote>
By default a template gives a single definition to be used for
every template argument (or combination of template arguments)
that a user can think of. This doesn't always make sense for
someone writing a template. I might want to say, ''if the
template argument is a pointer, use this implementation; if it
is not, use that implementation'' or give an error unless the
template argument is a pointer derived from class My_Base.
<end quote>


So, if you use specialization, all container instantiations
which contain pointers will share the same implementation. This
reduces object code bloat with several orders of magnitude in
common situations.

> Like suppose *shock* you want to call methods off of the pointers
> that are declared (void *) in your grungy internal implementation?

No you don't. The resulting instantiated type is still fully
type safe and you will be calling off methods on things that
are MyObject* in your code.

> What if you are parameterizing over two different types T1 and T2?
> Will your void * laden intermediate representation use it for
> both interchangably?

It will use the same implementation, but the compiler sees
that T1 and T2 are different and fail to compile. Remember that
C++ extracts type information from _headers_ not from _object_
files. So although the implementation in the _object_ file
is shared and hence could be used interchangably, the
compiler takes it's knowledge from the headers where the original
full types are specified.

> :#include <vector>
> :
> :void f (int i)
> :{
> : vector< int > vec;
> : vec.push_back (i);
> : vec.push_back (10);
> :}
> :
> :int main ()
> :{
> : int i;
> : initialize_i (i);
> : f (i);
> : g (i); // some other function
> : /* do rest of program */
> :}
> :
> :Trivial example, but can you get such hands-free memory management in Java ?

> and suppose in f you assigned a globally available pointer
> vec2 to vec?

I am not really sure what the original poster meant with this example,
but you can't assign a pointer vec, which is of type std::vector<class T>
and is not a pointer, but a simple variable.

> Unless you make aliases which is precisely problem that global garbage
> collection solves that isolated local per-class schemes insensitive
> to global dataflow and assignment of references cannot solve.

Indeed. I am uncertain as to what the original poster meant to demonstrate.
Aliasing is what makes garbage collection difficult. Maybe the
original poster wanted to say that C++ allows you to write programs where
there is no need to create aliases. For example : if your objects
are small, it might very well suffice to always copy them.

For larger, non-trivial programs this might not always hold true or
may impose a severe penalty on the programmer who has to seek ways
to prevent aliases. Suffices it to say that garbage collection is
used in larger C++ projects in varying degrees. (from std::auto_ptr<>
to full blown GC schemes comparable with Java)

> By your example the "you can fix C++ but only by massive perversions
> and virtuoso hacking" myth appears to be true. Also look at source
> code for a STL implementation as compared to, e.g. an Eiffel library.

So? If you think there is a need for a clean STL implementation
then you are free to write one. There is nothing in the standard
that mandates an implementation of the STL to be difficult.

Also, since this is a Java group, why don't you compare with
an implementation of the java library?

> :Somewhere, in another thread the notion arose that typical C++
> :derived class object layout strategy (contiguous) was slow.
> :
> :I see claims that stack allocation is thought to be equivalent
> :to heap allocation in terms of speed. rubbish.
> Oddly enough these are often backed up by empirical testing and
> published in journals. Of course the GC's are usually high-quality
> ones as in Smalltalk and Lisp and not Java implementations.

But of course, in the real world people are still using
block allocators, setting aside buffer pools and doing stack
allocation to prevent mallocs. Stack allocation is easy, well
understood and translates to 1 machine instruction for all
allocations in the same stack frame.

I'll beg for a malloc()/new that has the same properties.

> After experiencing that a few times I learned to stop worrying and
> love Garbage Collection, it's the Bomb.

Sure.

What would a state-of-the-art Java compiler do if it needs to
create a new object for which it can prove that no extra
references are ever passed outside the stackframe in which
this object is created?

I'd like my compiler to stack-allocate that one. And I am sure
that will be a major win.

Bart.Van...@nowhere.be

unread,
Jun 8, 2001, 6:16:36 AM6/8/01
to
Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote:
> Bart> Generics certainly lead to bigger binaries although that's
> Bart> only a problem in the embedded world.
> This is not generically (!) true. Generics do not always
> lead to bigger binaries. They may do so in C++ but there again C++ has
> a thoroughly knackered type system. The proposal for Java would not
> result in bigger binaries (or at only of the order of a few bytes per
> class, per method).

This has nothing to do with the thoroughly knackered type system,
but with the way generics are implemented. The current Java proposal
will indeed _not_ lead to bigger binaries, but on the other hand
introduced a lot of other limitations. (no instantiation on
basic types, no generic types as type arguments themselves
and no type safety all the way to name the most important ones)

Bart.Van...@nowhere.be

unread,
Jun 8, 2001, 6:43:43 AM6/8/01
to
Matt Kennel <SPAMBGONEmbke...@yahoo.com> wrote:
> With appropriate compiler technology generics don't cause much bloat---
> if you don't need arbitrary dynamic loading of new classes that
> might possibly call any feature in parameterized classes.

This is only a band-aid. In larger projects enough features
of enough containers with different template parameters will
eventually get called to qualify as 'bloat'.

> Free Sather and Eiffel compilers do some dataflow analysis to find the
> transitive closure of all possible routines that might be called in
> the program with the parameterization as actually used and
> specialized. This means that the library designer could write a very

That sounds like a fancy way of just having a linker that throws
away members/functions/... that are never called.

Use of the word closure gives me the chills. It might be silly
but it makes me think of a certain part of the academic
community that proposes so called state of the art technology
that never gets popular in the real world. While complaining
how there latest pet programming language get's seriously
neglected despite the abundance of closures and other fancy
words, so called academics neglect useability and the need to
adapt to a legacy-for-a-reason anchored-in-the-real-world
tool chain...

> heavy and full-featured generic class and when the user wants just
> one or two specializations and only uses the most elementary features
> of them, only the code for those features was ever generated.

This also reminds me of some good advice. Keep your interface
as small as possible, but no smaller. I feel that feature-heavy
class interfaces are usually a sign of bad design. The prime
feature of an interface designer is the ability to choose
effectivily. For he makes decisions for many others.

Every time I see this

public class SomeClass
{
...

public void Move(int, int) ...
public void Move(MyPoint) ...
}

I think : if the designer couldn't decide between these two, how
could he decide between a lot of other much more important issues
in designing his API?

> This strategy is highly effective; generics in Eiffel and Sather
> make much less bloat than in typical C++ implementations and yet
> are often have fully specialized new code generated for each type
> instantiation for maximum speed.

I must confess that I don't know anytyhing about Eiffel nor Sather.
After all, I write code for a living, not for a studying. Is there
a good overview on how they choose to deal with generics
available on the web?

> :No, it wont because the proposed addition to the standard doesn't
> :allow non-class types as type parameters for generic classes.

> Well actually I think that things like integers, floating point
> numbers and complex versions thereof really should be instances of
> classes, but they should NOT be accessed by reference variables, but
> by 'value' variables. Why should 'class' be isomorphic to
> 'only accessible by references that can be aliased'?

What would be the advantage to give int and other basic types
class - status without giving them the advantages of said status?

zeno

unread,
Jun 8, 2001, 6:34:51 AM6/8/01
to
The compiler will not compile this -- the parameter types (Integer & String) are not
compatible. This is the great part: a lot of type checking at compile
time and reduced checking at runtime.

// compiler error: Parameter String is not descendant of Integer


List<Integer> sl = new ArrayList<String>();

sl.add("hello"); // compiler error: "hello" is not of type Integer

Zeno


"Roger L. Cauvin" <rca...@homemail.com> wrote in message news:<9fnr82$56od8$1...@ID-20080.news.dfncis.de>...


> How does Java generics handle the following case:
>

> List<Integer> sl = new ArrayList<String>();
> sl.add("hello");
>

> Does the compiler flag complain about attempting to add a string to a list
> of integers?

Jon Skeet

unread,
Jun 8, 2001, 6:48:01 AM6/8/01
to
Bart.Van...@nowhere.be <Bart.Van...@nowhere.be> wrote:
> > If you have a parameterised class then I don't think
> > that you can parameterise over a parameterised type (ie you can't
> > instantiate an object as new Blah<List<Integer>>, although I could be
> > wrong about this.
>
> That would also be a pity.

Indeed it would - but fortunately it's not true :)

import java.util.*;

public class Test
{
public static void main (String [] args)
{
List<List<Integer>> lli = new ArrayList<List<Integer>>();

List<Integer> first = new ArrayList<Integer>();
List<Integer> second = new ArrayList<Integer>();

first.add (new Integer(1));
second.add (new Integer(2));

lli.add (first);
lli.add (second);

System.out.println (lli.get(0).get(0));
System.out.println (lli.get(1).get(0));
}
}

produces

1
2

as expected.

Phillip Lord

unread,
Jun 8, 2001, 8:34:15 AM6/8/01
to
>>>>> "Roedy" == Roedy Green <ro...@mindprod.com> writes:

Roedy> On 07 Jun 2001 12:23:09 +0100, Phillip Lord
Roedy> <p.l...@hgmp.mrc.ac.uk> wrote or quoted :

>> Generics do not always lead to bigger binaries. They may do so in
>> C++ but there again C++ has a thoroughly knackered type system.

Roedy> In which languages are you familiar with how generics work
Roedy> under the hood?

Under the hood? Not many, being essentially C++ and Java
(or about six different proposals for Java!).

In terms of just out of the hat type system the best one
which is widely used would probably be ML I would think. I am not sure
how its implemented under the hood, but given that the strength of the
type system per se I would guess its implemented very well!

Roedy> Which of these do you think got it most right? Which do you
Roedy> think would be the best model for Java, given any boxes Java
Roedy> has already got itself into with upward compatibility?

The best system I saw for Java was the one which came
from Stamford I think. It introduced two new byte codes, and got back
a very expressive type system.

Phil

Phillip Lord

unread,
Jun 8, 2001, 8:37:01 AM6/8/01
to
>>>>> "Mats" == Mats Olsson <ma...@dtek.chalmers.se> writes:


Bart> What happens when you pass a List that contains more than just
Bart> Integers? Failed casts at runtime?
>> No. If you dealing with a legacy library which has not been
>> parameterised then its got to cope with mixed lists anyway.

Mats> It's the other way around. Running code written for 1.4 or
Mats> earlier on the 1.5 class library after its APIs have been
Mats> rewritten to use generics will be possible without needing to
Mats> modify the 1.5 JVM. In fact, you can run the 1.5 class lib on
Mats> a 1.4 JVM, IIUC.

And you can use parametric classes on a non parametric JVM?
In otherwords 1.5 collections would work on 1.4 right?


Phil

Jorn W Janneck

unread,
Jun 8, 2001, 8:40:11 AM6/8/01
to

"Phillip Lord" <p.l...@hgmp.mrc.ac.uk> wrote in message
news:vfhexrj...@cs.man.ac.uk...

yes, that's the reason given for this strange design.

-- j


Phillip Lord

unread,
Jun 8, 2001, 8:40:27 AM6/8/01
to

>>>>> "Bart" == Bart Vanhauwaert <Bart.Van...@nowhere.be> writes:

Bart> Use of the word closure gives me the chills. It might be silly
Bart> but it makes me think of a certain part of the academic
Bart> community that proposes so called state of the art technology
Bart> that never gets popular in the real world. While complaining
Bart> how there latest pet programming language get's seriously
Bart> neglected despite the abundance of closures and other fancy
Bart> words, so called academics neglect useability and the need to
Bart> adapt to a legacy-for-a-reason anchored-in-the-real-world tool
Bart> chain...


Do you have a particular reason for limiting the tendency
to like doing things one familiar way to the exclusion of other
possible better technologies to academics, or are you just prejudiced?

Phil

Phillip Lord

unread,
Jun 8, 2001, 8:41:50 AM6/8/01
to
>>>>> "Bart" == Bart Vanhauwaert <Bart.Van...@nowhere.be> writes:

Bart> Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote: Generics certainly
Bart> lead to bigger binaries although that's only a problem in the
Bart> embedded world.


>> This is not generically (!) true. Generics do not always lead to
>> bigger binaries. They may do so in C++ but there again C++ has a
>> thoroughly knackered type system. The proposal for Java would not
>> result in bigger binaries (or at only of the order of a few bytes
>> per class, per method).

Bart> This has nothing to do with the thoroughly knackered type
Bart> system, but with the way generics are implemented.

Yeah it does. C++ type system is thoroughly knackered,
rather than just being knackered because its both crap in its
interface and its implementation.


Bart> The current Java proposal will indeed _not_ lead to bigger
Bart> binaries, but on the other hand introduced a lot of other
Bart> limitations.

Yeah I know.

Phil

Jorn W Janneck

unread,
Jun 8, 2001, 8:42:35 AM6/8/01
to

"Phillip Lord" <p.l...@hgmp.mrc.ac.uk> wrote in message
news:vfn17jj...@cs.man.ac.uk...

sounds like you are referring to PolyJ? in that case it's mit.

regards,

-- j

Jorn W Janneck

unread,
Jun 8, 2001, 8:49:37 AM6/8/01
to

<Bart.Van...@nowhere.be> wrote in message
news:v8aqf9...@10.0.0.2...
> Matt Kennel <SPAMBGONEmbke...@yahoo.com> wrote:
[snip]

>
> > Free Sather and Eiffel compilers do some dataflow analysis to find the
> > transitive closure of all possible routines that might be called in
> > the program with the parameterization as actually used and
> > specialized. This means that the library designer could write a very
>
> That sounds like a fancy way of just having a linker that throws
> away members/functions/... that are never called.
>
> Use of the word closure gives me the chills. It might be silly
> but it makes me think of a certain part of the academic
> community that proposes so called state of the art technology
> that never gets popular in the real world. While complaining
> how there latest pet programming language get's seriously
> neglected despite the abundance of closures and other fancy
> words, so called academics neglect useability and the need to
> adapt to a legacy-for-a-reason anchored-in-the-real-world
> tool chain...
[snip]

> > This strategy is highly effective; generics in Eiffel and Sather
> > make much less bloat than in typical C++ implementations and yet
> > are often have fully specialized new code generated for each type
> > instantiation for maximum speed.
>
> I must confess that I don't know anytyhing about Eiffel nor Sather.

apparently this fact does not cue you to suppress the 'academics-bash'
response above.

> After all, I write code for a living, not for a studying.

that doesn't look mutually exclusive to me. i also do not see how the fact
that you write code for a living precludes you from having a look at
state-of-the art programming languages. how can you choose the most
effective tool for your job without studying the ideas out there?

regards,

-- j


Phillip Lord

unread,
Jun 8, 2001, 8:49:55 AM6/8/01
to
>>>>> "Bart" == Bart Vanhauwaert <Bart.Van...@nowhere.be> writes:

Bart> Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote: What happens when
Bart> you pass a List that contains more than just Integers? Failed
Bart> casts at runtime?


>> No. If you dealing with a legacy library which has not been
>> parameterised then its got to cope with mixed lists anyway.

Bart> Indeed. But basically the other way around you can have
Bart> problems? Ie. an old style class passing a mixed List to a
Bart> new style class expecting a List<Integer>. Or is there some
Bart> mechanism to prevent this? And is there a mechanisme to
Bart> prevent one class passing a List<Integer> to another expecting
Bart> a List<MyType> for example?


Okay so I understand what you are asking.

The new library would be expecting things of type
List<extends Integer>, or in others words Lists with a) elements of a
common super type, and b) this super type should have a super class of
Integer (inc Integer itself).

As I am not 100% sure about what would happen here. I think
that it is likely that when compiling the library class (obviously
with a generic competent compiler) you would get an unchecked
warning. And it would of course crash when used incorrectly with a non
generic JVM.

Of course it is also true that you might write a library
requiring a List with only Integers in it with the current non generic
system, and this would also crash when misused, so there is no real
difference here. The only possible disadvantage that I can see is that
when writing the parametric library because the constraint of using
only Integer Lists is explicit in the code base, the programmer might
not mention this part of the contract in documentation, which was the
only way to enforce things previously.


>> If you have a parameterised class then I don't think that you can
>> parameterise over a parameterised type (ie you can't instantiate
>> an object as new Blah<List<Integer>>, although I could be wrong
>> about this.

Bart> That would also be a pity.

Its been suggested that I am indeed wrong about this.


Bart> I don't see this as an advantage of the current proposal
Bart> actually.
>> You do get a additional compile time safety. Not all the time but
>> some of it at least.

Bart> This is a mixed blessing. On the other hand I see why this
Bart> decision has been taken.

Yes I agree.

Phil

Jorn W Janneck

unread,
Jun 8, 2001, 9:10:41 AM6/8/01
to

<Bart.Van...@nowhere.be> wrote in message
news:mp7qf9...@10.0.0.2...
> Matt Kennel <SPAMBGONEmbke...@yahoo.com> wrote:
[huge snip]

> What would a state-of-the-art Java compiler do if it needs to
> create a new object for which it can prove that no extra
> references are ever passed outside the stackframe in which
> this object is created?
>
> I'd like my compiler to stack-allocate that one. And I am sure
> that will be a major win.

yes, it would. unfortunately, the java compiler cannot do this (at least not
the one compiling to byte code), because the constructor of the object or
any of its methods may pass a reference outside of the dynamic context. and
even if it does not 'currently', a future version still could. (and binary
compatibility requires that this works without a recompile.)

however, a class loader/jit could, in principle, be smarter, because once
the class is loaded, it is guaranteed not to change (the debugger interface
can tunnel this rule, of course). (even loading a class of the same name
does not change the original class definition.)

regards,

-- j


Mats Olsson

unread,
Jun 8, 2001, 9:18:19 AM6/8/01
to
In article <745qf9...@10.0.0.2>, <Bart.Van...@nowhere.be> wrote:
>Phillip Lord <p.l...@hgmp.mrc.ac.uk> wrote:
>> Bart> What happens when you pass a List that contains more than just
>> Bart> Integers? Failed casts at runtime?
>> No. If you dealing with a legacy library which has not been
>> parameterised then its got to cope with mixed lists anyway.
>
>Indeed. But basically the other way around you can have problems?
>Ie. an old style class passing a mixed List to a new style class
>expecting a List<Integer>.

Well, that would be strange - if calling with a mixed List was
ok before, then the new API can't start demanding a non-mixed Lists...

>Or is there some mechanism to prevent
>this? And is there a mechanisme to prevent one class passing a
>List<Integer> to another expecting a List<MyType> for example?

Only at compile time. At runtime, there is nothing left of the
generics (well, there is a section in the class file, but...)

/Mats

Phillip Lord

unread,
Jun 8, 2001, 10:23:24 AM6/8/01
to
>>>>> "Jorn" == Jorn W Janneck <jan...@REMOVETHIS-eecs.berkeley.edu> writes:

Jorn> sounds like you are referring to PolyJ? in that case it's mit.

Yeah I think you are correct. Its been a couple of years since
I looked at all of these proposals.

There was a proposal from Stanford

http://Theory.Stanford.EDU/~freunds/java-pt-oopsla.ps


which is why it stuck in my mind, but indeed you are
right that polyJ was the "two extra byte codes" one.

Phil

Phillip Lord

unread,
Jun 8, 2001, 10:29:19 AM6/8/01
to
>>>>> "Jorn" == Jorn W Janneck <jan...@REMOVETHIS-eecs.berkeley.edu> writes:

Jorn> <Bart.Van...@nowhere.be> wrote in message


>> It might be silly but it makes me think of a certain part of the
>> academic community that proposes so called state of the art
>> technology that never gets popular in the real world.

Jorn> apparently this fact does not cue you to suppress the
Jorn> 'academics-bash' response above.

>> After all, I write code for a living, not for a studying.

Jorn> that doesn't look mutually exclusive to me.


I have to agree with you that it doesn't. I am an academic. I
work with people who use write and use computer languages for
"studying" as it were. On the other hand I use computer languages as a
tool, as a means to end. I have always found that having the former
people around has stimulated me to learn new things, and have
increased my ability to write code dealing with highly complex data
issues.

Jorn> i also do not see how the fact that you write code for a
Jorn> living precludes you from having a look at state-of-the art
Jorn> programming languages. how can you choose the most effective
Jorn> tool for your job without studying the ideas out there?

Its my feeling that commercial programmers would benefit
greatly from increasing their knowledge in many different areas. From
talking to people who work in the private sector, their biggest
complaint seems to be that they get stuck on one project for ages, and
get "type-cast" based on their skill sets. For myself if I am
interesting in a new technology then I spend the time to learn it and
see what can be got out of it. I am fairly sure that I am a better
programmer for it.

Phil

Artur Biesiadowski

unread,
Jun 8, 2001, 10:32:43 AM6/8/01
to

Bart.Van...@nowhere.be wrote:

> Indeed. But basically the other way around you can have problems?
> Ie. an old style class passing a mixed List to a new style class
> expecting a List<Integer>. Or is there some mechanism to prevent
> this? And is there a mechanisme to prevent one class passing a
> List<Integer> to another expecting a List<MyType> for example?

Let's suppose that in old version library was asking for List of Strings
(in javadoc - signature was just List). Non-generic version of caller
just passed List, caring for correct filling by hand.

Now if we have new version of same library, which asks for List<String>,
old code can still use it without recompile. If you recompile with
generic-aware compiler, you will get a warning. If you recompile with
plain compiler, you do not get a warning - you are in same position as
with normal, non-parametric library - you have to watch for correct
contents yourself. There is no mechanism to prevent you from doing so.
There is also no mechanism which prevents you from passing Integer
object to reflection method awaiting String. In both cases you have to
watch for yourself. With new generics, you just are able to detect it
with compiler - sometimes. Not always. Generics do not relieve you from
thinking during programming.

Artur

Artur Biesiadowski

unread,
Jun 8, 2001, 10:42:15 AM6/8/01
to

Matt Kennel wrote:
>
> Free Sather and Eiffel compilers do some dataflow analysis to find the
> transitive closure of all possible routines that might be called in
> the program with the parameterization as actually used and
> specialized. This means that the library designer could write a very

> heavy and full-featured generic class and when the user wants just
> one or two specializations and only uses the most elementary features
> of them, only the code for those features was ever generated.

Let be honest. Compiler that have full view of entire program can do a
lot of things in very efficient and clean way. For me SmallEiffel is
really a good job - but it require full source for everything, including
core libs and third party libs. With such thing, if you want to build
monolithic library, you can really expect various global optimizations
from compiler, efficient multiple inheritance, lightweight generics etc.
Unfortunately we are talking about VERY dynamic environment, when you
don't even know next class that will be loaded. A lot of tricks from
SmallEiffel won't do here.

Artur

Jon A. Maxwell

unread,
Jun 8, 2001, 1:01:52 PM6/8/01
to
Jorn W Janneck <jan...@removethis-eecs.berkeley.edu> wrote: (comp.lang.java.advocacy)
|
| the original request quoted the following design goals:
:
| it explicitly did *not* include the following:
:
| the current proposal does not answer the request -- it violates
| the requirements (b) and (c) above, in order to obtain (a) below.

You're assuming that the original request was not flawed in what it
required and what was optional. If the original request was perfect
there would be no need to put it through the JCP at all.

| the reason is that List<Integer> (say) is *not* a proper type, the
| way String is, or Object, or Boolean [ ]. it is not represented at
| runtime as a class object, and thus contrary to all other (object)
| types, there is no way that i can distinguish, at runtime, an
| instance of class List<Integer> from an instance of List<String>

The <Integer> part refers to the type of the parameters and return
values (and implementation variables). So, why should List<Integer>
be a separate class from List? Normally a class is not defined by
the return values and parameter types of its methods, why should it
be any different for parameterized classes?

| this has several deep consequences.
|
| (1) for the first time in java, an object does not carry its
| complete type information around. this means that reflection is no
| longer complete -- the get-method of the class of an instance of
| List<String> has return type Object, rather than String (e.g.).

No, it means that an object's type is not determined by the types of
its method parameters -- which was never the case anyway. A List is
a List, whether you put Integers in it or Strings.

They do say that reflection should have support for identifying the
parameter types. But even if that's dropped, at runtime the String
type is barely worth discovering since at that time you better know
what you're doing or know how to handle exceptions. And if you want
the type info in a IDE, say, then some extra info is added to the
.class file to identify this information.

| (2) downcasting becomes a lot more complex. i cannot simply
| downcast any Object to, say, Map<String, Integer>, because there
| is no way that i could check this at runtime. the result is a set
| of complicated rules governing when i can downcast to a parametric
| type (cf. 5.3 in the proposal).

Of course you can cast Object to Map<String, Integer> -- if the
object is not a Map then you get a runtime exception. If you then
try to use it in a way incompatible with the parameter types you get
an exception. The <String, Integer> doesn't identify the object
type, Map, it identifies the parameter types and return types.

| (3) because things compile to regular jvm code, including all its
| typechecks, one of the potential benefits of generic types, viz.
| removing casts, cannot be realized. the casts are removed from the
| source-code, but they are automatically compiled into the
| bytecode. so even though the need to type them goes away, the
| runtime issue remains. (even though this is not a very big point,
| it *is* ugly, and small machines might very well benefit from the
| removal of casts.)

As somebody else pointed out, the speed cost of casts may more than
be made up for by not having the overhead of one class per
parameterized type or overhead of enforcing those types without
actually using multiple classes. Regardless, the cost of casting is
irrelevant except in the tightest loops.

| (3a) even worse though is this -- generic classes are normal java
| classes, i.e. they can be used without parameterizing them.
| because typecasts are implicit, we can now (for the almost first
| time, see 4) have a situation where a class cast exception is
| thrown without a cast being present in the source.

This is a good thing. It means that you don't have to write bridge
code between parts that use generic classes and those that do not.
IOW, templates won't necessarily "infect" non-template code. This
will actually a huge boon to the use of templates, because coders
will use them knowing that they won't needlessly irritate those
calling their code.

| (4) the decision not to make parameterized classes proper classes
| (i.e. represent them with distinct class objects) is also
| inconsistent with the way arrays are treated in java. arrays can
| be seen as a small specialized form of generic classes, and A []
| iand B [] are different classes:
|
| A [] a = new A[1]; B[] b = new B [1];
| System.out.println(a.getClass() == b.getClass())

Arrays are a special case, like primitive types, for speed. If they
behave like other parts of Java then that's convenient and nothing
more. How arrays behave is certainly no starting point for designing
how other features should. Perhaps instead arrays should be changed.

| so please let us discuss this proposal here, and maybe come up
| with something better. maybe we can even form a small group of
| people interested in this matter, and submit our objections to
| sun. the closing date is august 01, so we need to hurry somewhat.

Alternatively, maybe you'll conclude that Sun's version really is a
good thing.

Jam (address rot13 encoded)

Eric Gunnerson

unread,
Jun 8, 2001, 2:35:13 PM6/8/01
to
"Matt Kennel" <SPAMBGONEmbke...@yahoo.com> wrote in message
news:slrn9i01g2.nqf.SPAMB...@lyapunov.ucsd.edu...

> Bart.Van...@nowhere.be <Bart.Van...@nowhere.be> wrote:
> Free Sather and Eiffel compilers do some dataflow analysis to find the
> transitive closure of all possible routines that might be called in
> the program with the parameterization as actually used and
> specialized. This means that the library designer could write a very
> heavy and full-featured generic class and when the user wants just
> one or two specializations and only uses the most elementary features
> of them, only the code for those features was ever generated.
>
> This strategy is highly effective; generics in Eiffel and Sather
> make much less bloat than in typical C++ implementations and yet
> are often have fully specialized new code generated for each type
> instantiation for maximum speed.

I'm not sure whether it's a "typical" implementation, but Visual C++ does
template folding to (mostly) get rid of template bloat.


Matt Kennel

unread,
Jun 8, 2001, 2:57:46 PM6/8/01
to
On Fri, 08 Jun 2001 16:42:15 +0200, Artur Biesiadowski <ab...@pg.gda.pl> wrote:
:
:

:Matt Kennel wrote:
:>
:> Free Sather and Eiffel compilers do some dataflow analysis to find the
:> transitive closure of all possible routines that might be called in
:> the program with the parameterization as actually used and
:> specialized. This means that the library designer could write a very
:> heavy and full-featured generic class and when the user wants just
:> one or two specializations and only uses the most elementary features
:> of them, only the code for those features was ever generated.
:
:Let be honest. Compiler that have full view of entire program can do a
:lot of things in very efficient and clean way. For me SmallEiffel is
:really a good job - but it require full source for everything, including
:core libs and third party libs. With such thing, if you want to build
:monolithic library, you can really expect various global optimizations
:from compiler, efficient multiple inheritance, lightweight generics etc.

True, but in the case of SmallEiffel going to source is only because
there is no saved "pre-compiled" internal representation---with Java
bytecodes there is at least the possibility that the bytecode
representation would have enough information.

BTW I think SmallEiffel is spectacular.

:Unfortunately we are talking about VERY dynamic environment, when you


:don't even know next class that will be loaded. A lot of tricks from
:SmallEiffel won't do here.

I agree.

It is clear now that allowing arbitrary run-time loading of classes
which can call arbitrary things induces profound limitations on the
opportunities for high-quality compilation. The empirical consequence
appears to be that the run-time has to carry around a complicated
optimizing compiler. Oy Vey.

I suspect that in nearly all cases when programmers use these
features, only a few classes that are descendents a few types will be
loaded and they usually will only call a limited number of other
things.

I think there should be a standardized way to tell compilers
about this. I don't know if it should be in the language, in
the byte code or what but it needs to be there.

I thought that TowerJ had to address this problem and gaining full
static speed even in a mostly dynamic language was a major goal of the
Dylan project.

Java is not Smalltalk---more correctly, the needs and desires
of many Java programmers are not the same as Smalltalk programmers.

On one hand it is nice to have the potential for a fully dynamic
byte-code load-everything-on-the-fly system. On the other I see no
reason why somebody shouldn't be able to write a successful /bin/ls
compiled down-to-the-metal with performance, foot print
and startup time equal to C in Java either.

:Artur

--
* Matthew B. Kennel/Institute for Nonlinear Science, UCSD
*
* "To chill, or to pop a cap in my dome, whoomp! there it is."
* Hamlet, Fresh Prince of Denmark.

Jorn W Janneck

unread,
Jun 8, 2001, 3:02:17 PM6/8/01
to

"Phillip Lord" <p.l...@hgmp.mrc.ac.uk> wrote in message
news:vfu21rh...@cs.man.ac.uk...

but i had completely forgotten the stanford one -- thanks for the link!

-- j

Jorn W Janneck

unread,
Jun 8, 2001, 3:14:06 PM6/8/01
to

"Phillip Lord" <p.l...@hgmp.mrc.ac.uk> wrote in message
news:vfofrzh...@cs.man.ac.uk...

> I have to agree with you that it doesn't. I am an academic. I
> work with people who use write and use computer languages for
> "studying" as it were. On the other hand I use computer languages as a
> tool, as a means to end. I have always found that having the former
> people around has stimulated me to learn new things, and have
> increased my ability to write code dealing with highly complex data
> issues.
>
> Jorn> i also do not see how the fact that you write code for a
> Jorn> living precludes you from having a look at state-of-the art
> Jorn> programming languages. how can you choose the most effective
> Jorn> tool for your job without studying the ideas out there?
>
> Its my feeling that commercial programmers would benefit
> greatly from increasing their knowledge in many different areas. From
> talking to people who work in the private sector, their biggest
> complaint seems to be that they get stuck on one project for ages, and
> get "type-cast" based on their skill sets. For myself if I am
> interesting in a new technology then I spend the time to learn it and
> see what can be got out of it. I am fairly sure that I am a better
> programmer for it.

i agree completely with you. this notion of once learning 'how to program'
(as if this was a particular, very well-defined activity) and from then on
doing it professionally more or less without change until retirement has
always seemed very strange to me.

the best programmers i know, both in academia and industry, are people who,
very much like you said for yourself, keep abreast with the new things going
on out there. and that does not (only) mean the new versions of their tools,
but sticking your nose into popl or oopsla proceedings every once in a
while.

regards,

-- j

Jorn W Janneck

unread,
Jun 8, 2001, 4:02:53 PM6/8/01
to

"Jon A. Maxwell (JAM)" <wznk...@npz.ig.rqh> wrote in message
news:9fr0e0$o7$1...@solaris.cc.vt.edu...

> Jorn W Janneck <jan...@removethis-eecs.berkeley.edu> wrote:
(comp.lang.java.advocacy)
> |
> | the original request quoted the following design goals:
> :
> | it explicitly did *not* include the following:
> :
> | the current proposal does not answer the request -- it violates
> | the requirements (b) and (c) above, in order to obtain (a) below.
>
> You're assuming that the original request was not flawed in what it
> required and what was optional. If the original request was perfect
> there would be no need to put it through the JCP at all.

no, i am not *assuming* that. it is my personal *opinion* that the original
request, and specifically the design goals it stated, was reasonable and
well considered. you are right, i should have been clearer about that.

and you are also right, the request as such as certainly not something that
needs to be adhered to strictly. however, i think that any proposal
deviating from explicit design goals should address the pros *and cons* of
this decision a lot more explicitly than this proposal does. the reason is
that the design goals formulated in the original proposal were there for a
reason, and creating a design that fundamentally does not meet the original
goals should, imho, explain what was lost because of it.

it seems to me that the current proposal sweeps this issue pretty much under
the rug. only in passing does it mention the fact that it significantly
revises the design goals (reversing some in the process), and it does not at
all illuminate the consequences of this decison. if you followed this
thread, half a dozen of good people were struggling to figure out exactly
what the limitations are the follow from the proposed design.

> | the reason is that List<Integer> (say) is *not* a proper type, the
> | way String is, or Object, or Boolean [ ]. it is not represented at
> | runtime as a class object, and thus contrary to all other (object)
> | types, there is no way that i can distinguish, at runtime, an
> | instance of class List<Integer> from an instance of List<String>
>
> The <Integer> part refers to the type of the parameters and return
> values (and implementation variables). So, why should List<Integer>
> be a separate class from List?

(1) because it is a different 'type', and all user defined types in java
were (so far) represented as a different class object.
(2) because if i want to cast an arbitrary object to this type, i need a way
to figure out whether it *is* of that type. the usual way this is done in
java is by examining the class object that the original object referred to.
if this is List for a List<Integer> and a List<String>, i have no way of
distinguishing those at run time.

> Normally a class is not defined by
> the return values and parameter types of its methods, why should it
> be any different for parameterized classes?

i do no t understand this remark -- clearly, the signatures of a method are
*part* of the definition of a class?

> | this has several deep consequences.
> |
> | (1) for the first time in java, an object does not carry its
> | complete type information around. this means that reflection is no
> | longer complete -- the get-method of the class of an instance of
> | List<String> has return type Object, rather than String (e.g.).
>
> No, it means that an object's type is not determined by the types of
> its method parameters -- which was never the case anyway. A List is
> a List, whether you put Integers in it or Strings.

so that means you think List<String> should be assignment-compatible to
List<Integer>? the whole point of generic classes is that it does indeed
matter what other types you use and object with, at least from a type system
perspective.

why isn't an array an array, irrespective of what is stored in it?

Integer [] a = new Integer[0];
String [] b = new String [0];
System.out.println(a.getClass() == b.getClass());

try it, and explain to me what the in-principle difference between an array
and a list is, from a language design perspective.

> They do say that reflection should have support for identifying the
> parameter types. But even if that's dropped, at runtime the String
> type is barely worth discovering since at that time you better know
> what you're doing or know how to handle exceptions. And if you want
> the type info in a IDE, say, then some extra info is added to the
> .class file to identify this information.

the point is that one part of your system creates a List<Integer>, and some
other part uses reflection (or whatever) to manipulate that list, putting
e.g. strings in it, while the rest of the program still assumes (and in fact
has been statically guaranteed) that there are only integers in it. so you
can tunnel the static type information via reflection, something you cannot
do now.

> | (2) downcasting becomes a lot more complex. i cannot simply
> | downcast any Object to, say, Map<String, Integer>, because there
> | is no way that i could check this at runtime. the result is a set
> | of complicated rules governing when i can downcast to a parametric
> | type (cf. 5.3 in the proposal).
>
> Of course you can cast Object to Map<String, Integer> -- if the
> object is not a Map then you get a runtime exception.

yes, but the point is that the cast to Map<String, Integer> contains more
information than that. it says that the object is a map that accepts strings
as keys and produced integers as values. it is my view that the type system
infrastructure shouls have a way to ascertain these facts, and that the
runtime infrastructure should have a way to maintain their truth.

> If you then
> try to use it in a way incompatible with the parameter types you get
> an exception. The <String, Integer> doesn't identify the object
> type, Map, it identifies the parameter types and return types.

you are looking at it from only one side:

void f(Object a) {
Map<String, Integer> m = (Map<String, Integer>)a;
// here i can only use m as such a map
// as you correctly say
}

however, i can do

Map<BigInteger, Boolean> m = new ...
// fill this map
f(m);

there would be no way to detect this problem at the time of the cast in f. f
could pass the map around, or even worse store it and some other code later
uses it, and an exception will only be thrown when i access an element in
the map (i can even add 'wrong' elements to the map, thus mixing the stuff
in it).

this is why casts such as the one in f are not even legal in the current
proposal. you just cannot do them. this shows that parametric types are
second class, and i think that sucks.

> | (3) because things compile to regular jvm code, including all its
> | typechecks, one of the potential benefits of generic types, viz.
> | removing casts, cannot be realized. the casts are removed from the
> | source-code, but they are automatically compiled into the
> | bytecode. so even though the need to type them goes away, the
> | runtime issue remains. (even though this is not a very big point,
> | it *is* ugly, and small machines might very well benefit from the
> | removal of casts.)
>
> As somebody else pointed out, the speed cost of casts may more than
> be made up for by not having the overhead of one class per
> parameterized type or overhead of enforcing those types without
> actually using multiple classes. Regardless, the cost of casting is
> irrelevant except in the tightest loops.

yes, but it does not fit the current design for arrays -- here, we actually
*do* have one class per parametric instance. why's that? because it's the
only way to guarantee type safety dynamically for arrays in the same way as
for other user-defined classes.

> | (3a) even worse though is this -- generic classes are normal java
> | classes, i.e. they can be used without parameterizing them.
> | because typecasts are implicit, we can now (for the almost first
> | time, see 4) have a situation where a class cast exception is
> | thrown without a cast being present in the source.
>
> This is a good thing. It means that you don't have to write bridge
> code between parts that use generic classes and those that do not.

no it's not, because it means that you can have class cast exceptions in
places that you thought were statically type safe.

> IOW, templates won't necessarily "infect" non-template code. This
> will actually a huge boon to the use of templates, because coders
> will use them knowing that they won't needlessly irritate those
> calling their code.

actually, i think it's wrong to consider type parameters like viruses which
are infecting code. they are a key to the type-safe reusability of code, and
should be seen as such. people use type parameters whenever they write
"String []" in their main method, and i do not see why this shouldn't be the
same for user-defined classes.

in languages where parametric types are well-designed, people have no
problems using them in the same way they think of arrays as being arrays of
something. it is usually people with a c++ background who consider generic
types as complicated beasts that have to be used with extreme caution,
rather than as a normal part of the signature of your class.

one of the things that i think is at stake here is that the current design
for java might actually further support this wrong-headed view, rather than
presenting generic types as a simple but effective way to make class
interfaces flexible and still type-safe.

> | (4) the decision not to make parameterized classes proper classes
> | (i.e. represent them with distinct class objects) is also
> | inconsistent with the way arrays are treated in java. arrays can
> | be seen as a small specialized form of generic classes, and A []
> | iand B [] are different classes:
> |
> | A [] a = new A[1]; B[] b = new B [1];
> | System.out.println(a.getClass() == b.getClass())
>
> Arrays are a special case, like primitive types, for speed.

what does this have to do with speed?

> If they
> behave like other parts of Java then that's convenient and nothing
> more. How arrays behave is certainly no starting point for designing
> how other features should. Perhaps instead arrays should be changed.

but why? why should we remove even the little illusion of static type safety
from the one generic class that we have, rather than adding more static type
safety to the language?

> | so please let us discuss this proposal here, and maybe come up
> | with something better. maybe we can even form a small group of
> | people interested in this matter, and submit our objections to
> | sun. the closing date is august 01, so we need to hurry somewhat.
>
> Alternatively, maybe you'll conclude that Sun's version really is a
> good thing.

i do not conclude that. i think it may very well be an irreversible wart in
the design of the java language. there are good parametric type systems out
there, and java should mix its own strengths with them, rather than just
trying to be a little better than c++ templates.

maybe you like this design, but then i didn't understand why. i think the
only defensible advantage is it's complete compatibility to everything that
is java already, but it did not seem like this was something you found very
important. other than that, i just do not see one single thing that is good
about this proposal.

regards,

-- j


Bart.Van...@nowhere.be

unread,
Jun 8, 2001, 5:15:30 PM6/8/01
to
Jorn W Janneck <jan...@removethis-eecs.berkeley.edu> wrote:
>> I must confess that I don't know anytyhing about Eiffel nor Sather.
> apparently this fact does not cue you to suppress the 'academics-bash'
> response above.

I fail to see why it should.

I should note that my 'bash' was specifically a reacting on something
trivial desguised behind fancy words (of which closure is a prime
example). Of course, I could've misunderstood the original poster,
but so far no one seems to want to correct me.

>> After all, I write code for a living, not for a studying.
> that doesn't look mutually exclusive to me. i also do not see how the fact
> that you write code for a living precludes you from having a look at
> state-of-the art programming languages. how can you choose the most
> effective tool for your job without studying the ideas out there?

I'll let you know the day everyone else on the projects
I work on switches over to Eiffel or Sather. Until then, someone
proposing those languages as a serious alternative for real
world development is living in a dream world.

I am sorry to burst your bubble but outside berkeley the world
doesn't move as fast as you might like it to.

One might be the best programmer in the world, but if one cannot
take advantage of a vast experience built around legacy code
in legacy languages on legacy platforms, one is bound to fail
for large scale development.

If I could make a legally binding bet in the country where I live
in (which i can't), i'd gladly accept a bet with you for say $1000
that in 5 years not _1_ acedemic language as we know them now
will be generally accepted as for example Java or heaven's forbid
C/C++ currently are. Would you accept such a bet?

Jorn W Janneck

unread,
Jun 9, 2001, 9:28:26 AM6/9/01
to

<Bart.Van...@nowhere.be> wrote in message
news:i9frf9...@10.0.0.2...

> Jorn W Janneck <jan...@removethis-eecs.berkeley.edu> wrote:
> >> I must confess that I don't know anytyhing about Eiffel nor Sather.
> > apparently this fact does not cue you to suppress the 'academics-bash'
> > response above.
>
> I fail to see why it should.

imho, because it would be very appropriate.

> I should note that my 'bash' was specifically a reacting on something
> trivial desguised behind fancy words (of which closure is a prime
> example). Of course, I could've misunderstood the original poster,
> but so far no one seems to want to correct me.

well, let's see.

(1) the closure concept may be trivial to you, but it certainly isn't from a
programming language implementation perspective, which explains why
virtually no popular language actually has a full implementation of them
(most functional languages do, and so does smalltalk, and a few other
languages with a smaller user base, but neither c++ nor java nor vb nor
pascal or so does. besides, it's a not a particularly fancy term, it's
simply the technical term for a particular implementation strategy of a
particular feature. you know of a better one?

(2) but unfortunately that was not at all the kind of closure that matt was
talking about. a 'transitive closure' of a relation (in this case, i
believe, the call graph of a program) is the smallest transitive relation
that contains the original relation.

so yes, you misunderstood the poster, but even if he would have said what
you think he did, your reaction would have been totally inappropriate. imo.

> >> After all, I write code for a living, not for a studying.
> > that doesn't look mutually exclusive to me. i also do not see how the
fact
> > that you write code for a living precludes you from having a look at
> > state-of-the art programming languages. how can you choose the most
> > effective tool for your job without studying the ideas out there?
>
> I'll let you know the day everyone else on the projects
> I work on switches over to Eiffel or Sather.

that's not required, but thanks for the offer.

> Until then, someone
> proposing those languages as a serious alternative for real
> world development is living in a dream world.

strong words from someone with admittedly no knowledge of the languages in
question. apart from that, nobody actually suggested them for anything. imo,
it is a good thing to know the ideas out there in order to choose the proper
tools. that's not to say you should use eiffel, but i think it does not hurt
to know what is good and bad about it, even if it only puts the tools you
end up using in proper perspective, both in their strengths and
shortcomings. arguing from a position of ignorance is unlikely to impress
anyone.

> I am sorry to burst your bubble but outside berkeley the world
> doesn't move as fast as you might like it to.

you condescension is not appreciated. i could simply answer that maybe in
belgium things are particularly slow, but that would as arrogant and foolish
(and unfair to the many smart people in that country) and totally
inappropriate as your remark, so i won't.

> One might be the best programmer in the world, but if one cannot
> take advantage of a vast experience built around legacy code
> in legacy languages on legacy platforms, one is bound to fail
> for large scale development.

what does this have to do with anything?

> If I could make a legally binding bet in the country where I live
> in (which i can't), i'd gladly accept a bet with you for say $1000
> that in 5 years not _1_ acedemic language as we know them now
> will be generally accepted as for example Java or heaven's forbid
> C/C++ currently are. Would you accept such a bet?

so then, what exactly *is* an 'academic' language? you are aware, aren't
you, that c and c++ were not designed by microsoft? do research labs count
as 'academia'?

and even if we defined that term, and we made that bet, and you won it, what
precisely would that show? that ignorance is a good thing? what is the point
you want to make? that we should stop doing research on programming
languages and let you and microsoft design all future programming notations?
that we should even stop critiquing those designs and start liking them?
that a crappy design is a good thing when someone argues for it with
uninformed anti-intellectualist prejudices masquerading as business sense?

so rather than offering me a bet, why don't you tell me what the point is
you are trying to make, and offer some supporting arguments that do not rest
on your self-assumed authority in all matters practical.

best regards,

-- j

Bart.Van...@nowhere.be

unread,
Jun 9, 2001, 4:35:01 PM6/9/01
to
Jorn W Janneck <jan...@removethis-eecs.berkeley.edu> wrote:
>> example). Of course, I could've misunderstood the original poster,
>> but so far no one seems to want to correct me.
> (2) but unfortunately that was not at all the kind of closure that matt was
> talking about. a 'transitive closure' of a relation (in this case, i
> believe, the call graph of a program) is the smallest transitive relation
> that contains the original relation.

The original poster was talking about compilers doing a full text
analysis to deduce which members of a generic type actually have
to be instantiated.

One does not need to be very bright to see that such is impractical
for larger projects (because the full text is not always available)
and that it would be simpler to do said analysis at linkage by
throwing out unreferenced instantiated members. Tecnically, it's the
same simple trick. I prefer to keep simple things simple...

>> Until then, someone
>> proposing those languages as a serious alternative for real
>> world development is living in a dream world.
> strong words from someone with admittedly no knowledge of the languages in
> question. apart from that, nobody actually suggested them for anything. imo,
> it is a good thing to know the ideas out there in order to choose the proper
> tools. that's not to say you should use eiffel, but i think it does not hurt
> to know what is good and bad about it, even if it only puts the tools you
> end up using in proper perspective, both in their strengths and
> shortcomings. arguing from a position of ignorance is unlikely to impress
> anyone.

Sure, sure, that's perfectly reasonable. Unfortunatly, time is a limiting
factor. I try my very best to stay on top of things. After all, it's
what allows me to ask a certain price for my services. Unfortunatly,
knowing the basics of Sather&Eiffel is of smaller value than knowing
a detail of let's say MFC.

You might not like that, but it's a plain and simple thruth. Putting
'knowledge of Sather' on my resume will only result in people asking
why I have a reference to a mythical beast in there. Are they
ignorant? Am I ignorant?
No. I just prioritize things based on their value for someone
programming-for-a-living, because that is exactly what I do.

>> I am sorry to burst your bubble but outside berkeley the world
>> doesn't move as fast as you might like it to.
> you condescension is not appreciated. i could simply answer that maybe in
> belgium things are particularly slow, but that would as arrogant and foolish
> (and unfair to the many smart people in that country) and totally
> inappropriate as your remark, so i won't.

Actually, I work in France, and yes, there is no arguing about that.
The commercial world in France (and Belgium for that matter) moves
slower than inside an average university. And guess what. I think
that's good thing for productivity.

>> One might be the best programmer in the world, but if one cannot
>> take advantage of a vast experience built around legacy code
>> in legacy languages on legacy platforms, one is bound to fail
>> for large scale development.
> what does this have to do with anything?

That has to do with full text analysis as a suggestion to remove
code bloat generated from instantiation of generic types
is a less-usefull proposition given the current state of affairs.

> that a crappy design is a good thing when someone argues for it with
> uninformed anti-intellectualist prejudices masquerading as business sense?

Funny thing is that you seem to fail to have picked up that I gave
some perfectly valid 'common sense' guidelines that help reduce
bloat in the real world. Common sense guidelines
which, I am sure, have reduced code bloat a lot more than any
global analysis has.

Matt Kennel

unread,
Jun 9, 2001, 8:36:23 PM6/9/01
to
Bart.Van...@nowhere.be <Bart.Van...@nowhere.be> wrote:

:Jorn W Janneck <jan...@removethis-eecs.berkeley.edu> wrote:
:>> example). Of course, I could've misunderstood the original poster,
:>> but so far no one seems to want to correct me.
:> (2) but unfortunately that was not at all the kind of closure that matt was
:> talking about. a 'transitive closure' of a relation (in this case, i
:> believe, the call graph of a program) is the smallest transitive relation
:> that contains the original relation.
:
:The original poster was talking about compilers doing a full text
:analysis to deduce which members of a generic type actually have
:to be instantiated.
:
:One does not need to be very bright to see that such is impractical
:for larger projects (because the full text is not always available)
:and that it would be simpler to do said analysis at linkage by
:throwing out unreferenced instantiated members. Tecnically, it's the
:same simple trick. I prefer to keep simple things simple...

You can do it at link time or compile time, obviously you get the
same answer for finally generated code but the compiler had to
spit out more intermediate object code than it would have otherwise,
which you may think is a minor.

Notice that an algorithm that trivially deletes just 'unreferenced'
members isn't quite good enough. You could have some big libraries
where pieces of them have implementations that call pieces of the
other ones, and yet you never use either one of them in your program.
It is the same issue as garbage collection, except of course the
reference graph is static.

Focusing on 'text' versus 'object' misses the point that the issue
is over the costs of allowing unrestricted dynamic loading of
classes.

If you've never experienced the benefits then the absence of
some control doesn't seem significant.

:>> Until then, someone


:>> proposing those languages as a serious alternative for real
:>> world development is living in a dream world.
:> strong words from someone with admittedly no knowledge of the languages in
:> question. apart from that, nobody actually suggested them for anything. imo,
:> it is a good thing to know the ideas out there in order to choose the proper
:> tools. that's not to say you should use eiffel, but i think it does not hurt
:> to know what is good and bad about it, even if it only puts the tools you
:> end up using in proper perspective, both in their strengths and
:> shortcomings. arguing from a position of ignorance is unlikely to impress
:> anyone.
:
:Sure, sure, that's perfectly reasonable. Unfortunatly, time is a limiting
:factor. I try my very best to stay on top of things. After all, it's
:what allows me to ask a certain price for my services. Unfortunatly,
:knowing the basics of Sather&Eiffel is of smaller value than knowing
:a detail of let's say MFC.
:
:You might not like that, but it's a plain and simple thruth. Putting
:'knowledge of Sather' on my resume will only result in people asking
:why I have a reference to a mythical beast in there. Are they
:ignorant?

yes

:Am I ignorant?

at least you know about it now.

:No. I just prioritize things based on their value for someone


:programming-for-a-living, because that is exactly what I do.

The reason why commercial programmers should know about "exotic"
languages and their capabilities is so that they can recognize
mediocrity and deep excellence when they see it, and demand it from
their commercial suppliers.

aka

Do you want to be learning about MFC for the rest of your life?

:>> One might be the best programmer in the world, but if one cannot


:>> take advantage of a vast experience built around legacy code
:>> in legacy languages on legacy platforms, one is bound to fail
:>> for large scale development.
:> what does this have to do with anything?
:
:That has to do with full text analysis as a suggestion to remove
:code bloat generated from instantiation of generic types
:is a less-usefull proposition given the current state of affairs.

Because of multi-language linking? Is that what you're
getting at?

:--
:http://www.irule.be/bvh/

Jorn W Janneck

unread,
Jun 10, 2001, 1:13:19 AM6/10/01
to

<Bart.Van...@nowhere.be> wrote in message
news:l91uf9...@10.0.0.2...

> Jorn W Janneck <jan...@removethis-eecs.berkeley.edu> wrote:
> >> example). Of course, I could've misunderstood the original poster,
> >> but so far no one seems to want to correct me.
> > (2) but unfortunately that was not at all the kind of closure that matt
was
> > talking about. a 'transitive closure' of a relation (in this case, i
> > believe, the call graph of a program) is the smallest transitive
relation
> > that contains the original relation.
>
> The original poster was talking about compilers doing a full text
> analysis to deduce which members of a generic type actually have
> to be instantiated.
>
> One does not need to be very bright to see that such is impractical
> for larger projects (because the full text is not always available)
> and that it would be simpler to do said analysis at linkage by
> throwing out unreferenced instantiated members. Tecnically, it's the
> same simple trick. I prefer to keep simple things simple...

well, i seem to remember that he was talking about dataflow analysis, which
does not require any 'text', or does it?

but anyway it's beside the point, as you originally took issue with use of
the term 'closure'. since the term was both relevant and appropriate, your
criticism wasn't.

[snip]


> Sure, sure, that's perfectly reasonable. Unfortunatly, time is a limiting
> factor. I try my very best to stay on top of things. After all, it's
> what allows me to ask a certain price for my services. Unfortunatly,
> knowing the basics of Sather&Eiffel is of smaller value than knowing
> a detail of let's say MFC.
>
> You might not like that,

how you spend your time is really your private matter, and i have no opinion
about it.

> but it's a plain and simple thruth. Putting
> 'knowledge of Sather' on my resume will only result in people asking
> why I have a reference to a mythical beast in there. Are they
> ignorant? Am I ignorant?

i wouldn't dare to commit to any judgment at this point. clearly, you do not
know of certain things (like everybody), and as such are technically
ignorant about them. i cannot know whether this description fits you more
generally, nor do i want to find out.

> No. I just prioritize things based on their value for someone
> programming-for-a-living, because that is exactly what I do.

oddly, though, other people who also earn money as software engineers still
know quite a lot about these things. apparently, then, these two aren't as
mutually exclusive as you seem to want to make them out.

> >> I am sorry to burst your bubble but outside berkeley the world
> >> doesn't move as fast as you might like it to.
> > you condescension is not appreciated. i could simply answer that maybe
in
> > belgium things are particularly slow, but that would as arrogant and
foolish
> > (and unfair to the many smart people in that country) and totally
> > inappropriate as your remark, so i won't.
>
> Actually, I work in France, and yes, there is no arguing about that.
> The commercial world in France (and Belgium for that matter) moves
> slower than inside an average university. And guess what. I think
> that's good thing for productivity.

and again, there are companies moving extremely fast, much faster than
average universities, and they make money, too. a lot of it, in some cases.
so these factors, too, do not seem to be very related.

> >> One might be the best programmer in the world, but if one cannot
> >> take advantage of a vast experience built around legacy code
> >> in legacy languages on legacy platforms, one is bound to fail
> >> for large scale development.
> > what does this have to do with anything?
>
> That has to do with full text analysis as a suggestion to remove
> code bloat generated from instantiation of generic types
> is a less-usefull proposition given the current state of affairs.

see the dataflow remark. plus, i still do not understand the relation to
programmer quality or legacy anything. but well...

> > that a crappy design is a good thing when someone argues for it with
> > uninformed anti-intellectualist prejudices masquerading as business
sense?
>
> Funny thing is that you seem to fail to have picked up that I gave
> some perfectly valid 'common sense' guidelines that help reduce
> bloat in the real world. Common sense guidelines
> which, I am sure, have reduced code bloat a lot more than any
> global analysis has.

again, i fail to see how your reply has anything to do with what i said.

to be precise: i took issue with your uninformed dismissal of stuff you
haven't heard or knew anything about, and your judgment of its value, or the
value of insights gained from knowing about it. i took issue with your
objection to the use of terms you apparently did not understand, simply
*because* you did not understand them. i took issue with the fact that
simply because you currently happen to sit in a company in france, and i am
forced to spend my day at an educational institution in california, you make
fairly unwarranted assumptions about the relation between your and my
knowledge about practical matters.

since in all three cases it seems you objected to things you didn't have a
lot of knowledge about (you said so yourself in the first case, i
interpreted this from what you write or didn't write about the term
'closure' for the second case, and i simply assume you are not sufficiently
familiar with my biography (and why should you) in the third), i am left
with the conclusion that the answer to philip lord's question is, in fact,
"no", and that you are just prejudiced.

best regards,

-- j


bluke

unread,
Jun 10, 2001, 12:05:11 PM6/10/01
to
This "compiler magic" stuff is a bandaid. Any language where code
generation arises as a common implementation mechanism lacks the
flexibility to serve its intended domain. This fits Java to a t. First
it started with inner classes, now generics. This says to me that the
language was poorly designed from the start.

David Chase

unread,
Jun 10, 2001, 12:47:35 PM6/10/01
to
Jorn W Janneck wrote:

> (1) the closure concept may be trivial to you,
> but it certainly isn't from a programming language
> implementation perspective, which explains why
> virtually no popular language actually has a full
> implementation of them

There's "trivial", and there's trivial. The people who define the
languages often do not take anything like a long view, nor do they
necessarily have much experience in end-to-end language
implementation. The use of C as an intermediate language makes this
seem harder than it really is. If you consider the difficulty of
doing the optimizations done in a Fortran compiler, or the difficulty
of building a high performance Java Virtual Machine, closures *are*
trivial.

Problem is, the programming languages get defined before anyone is
ready/willing to dump serious resources on implementing them, and all
the allegedly "hard stuff" gets left out to make life easier for
the first implementers. Or, the language definers have no idea
what's actually easy and what's actually hard, and they avoid the
stuff that they think is hard.

Here's the recipe for implementing closures, since you think
it is so hard. The basic problem is that you need to inject
some data (e.g. a first parameter, or a hidden parameter) into
a procedure that you call. There are several knobs that you
might want to turn:

1. first parameter or hidden parameter?
"First parameter" is more general since it gives you partial
application (once the hidden parameter is used, it is used).

2. closure lives longer than binding site, or not?
Lifetime independent of binding site is a little harder since
then you need a garbage collector. But Java has one, so does
Eiffel, so does Modula-3, so does C#.

3. Thread safe
Ought to go without saying.

For a classical "closure" (capturing bindings from its lexical
context) you need (when compiling the lexical context) to
partition the variables into those that are closure-shared
and those that are not. Andrew Appel and his colleagues have
studied this problem, and it would be pay to follow their
advice. Where you partition to depends upon the lifetime
of the closure; if it survives the binding frame, then it has
to be on the heap, otherwise it can just be part of the frame.

(I've done this, "for part of the frame", in a Modula-3 compiler
that targeted C. That was the first compiler/runtime I worked
on after graduate school.) Notice that the partitioning
guarantees that if you don't use this feature, then there
is no effect on optimization, always a good goal.

The actual implementation strategy varies by architecture and ABI.
Where the ABI specifies parameters passed on the stack (Motorola
68k, Pentium cdecl) the thunk simply pushes an extra piece of
data (the new first parameter) onto the stack and then branches
to the "true procedure". I've done this on Motorola 68k (Modula-3).
I've also done a special case of this for Pentium.

For architectures that pass registers in parameters (MIPS,
Sparc, PowerPC, Pentium stdcall, IA-64), there is usually
a "spare" that can be used to pass a "hidden" parameter.
Hidden parameters can get you into trouble with
C-as-an-intermediate-language, since there's no portable way
to talk about those registers. Again, generate a thunk
that loads the hidden parameter.

Thunk generation also has to be considered carefully. Most
modern chips are not "happy" executing recently-written
data. The generated thunks must be known to the garbage
collector. The way I've done this in the past is to generate
thunks in bulk, and then allocate them and deallocate them
specially. The idea here is that you allocate two separate
regions, one for code, one for data, and then you generate
code blobs that are paired with data blobs (that is, a
specific code blob will load its target procedure and target
data from a specific data blob) and linked into a free list
through the data blobs. After the code blobs are all generated,
the whole page can be made ready for execution (flushed, possibly
remapped, whatever). Allocation is then just list allocation,
*except* that you need to worry about thread safety. For that,
you either use compare-and-swap to snag the top of the free list,
or else you reserve a per-thread cache of thunks.

The GC, in turn, needs to consider all pointers-to-code, to
check for any that are actually thunks, and to trace through
the thunks, both for the data (which is heap-allocated) and
for the code (which could be another thunk in the general
case of being able to add a first parameter).

> (2) but unfortunately that was not at
> all the kind of closure that matt was
> talking about. a 'transitive closure'
> of a relation (in this case, i
> believe, the call graph of a program)
> is the smallest transitive relation
> that contains the original relation.

What was the context of the transitive closure problem? Maintaining
an additive transitive closure is not the hardest problem in the
world, though it might be a space hog. Updating the transitive
closure after code or class deletion is more of a problem, except
that you have the GC as a crutch to guarantee that in a certain way,
it "does not matter". Even when there has been inlining of code,
the GC gives you a guarantee that the inlined code won't be executed
(though it is necessary to ensure that type tags and indices are
not reused until all the inlined code has been purged).

So, what's hard? These algorithms are not as hard as (say)
register allocation or scheduling. It's also all generally
old news -- over ten years ago, Thomas Breuel clued me in
to the thunk-generating trick for closures, I figured out
the icache-friendly thunk cache, did the visibility-partition
analysis for Modula-3, and generated thunks on the stack as
well (for Modula-3 on M68K with limited-lifetime "closures").
I reimplemented the thunk cache for the Sparc a few years
later, and passed along everything I knew to David Keppel
(aka "Pardo") then at U Washington, who I think incorporated
it into his RTCG toolkit.

David Chase

Jorn W Janneck

unread,
Jun 10, 2001, 1:01:55 PM6/10/01
to

"bluke" <marty...@hotmail.com> wrote in message
news:6dda2659.01061...@posting.google.com...

> This "compiler magic" stuff is a bandaid.

i am not quite sure what compiler magic you refer to, but it seems that a
proper implementation of generic classes in java requires relatively little
of it, compared, say, to the corresponding implementation in c++. it *does*
(would) require a little bit of interpreter magic, though.

> Any language where code
> generation arises as a common implementation mechanism lacks the
> flexibility to serve its intended domain.

what is your notion of 'code generation' here? you are clearly not talking
about 'code generation' in the sense that any compiler generates code, this
i understand.

> This fits Java to a t. First
> it started with inner classes, now generics. This says to me that the
> language was poorly designed from the start.

while i wouldn't defend java's design as a particularly good one, i think
inner classes are not a very good example for showing its shortcomings --
imo, this was integrated fairly well, even though, you are of course right
here, a little bit of compiler magic had to be done. neither are generics,
at least not in principle -- there is no reason why the java/jvm platform
could not be adapted to support a fairly useful notion of generic types, way
ahead of many popular languages, with a relatively small set of changes,
that would not disrupt the overall design. it's just that it looks like this
is not what is going to happen.

best regards,

-- j

It is loading more messages.
0 new messages