Why Generics?

  • Thread starter David Blickstein
  • Start date
T

Thomas G. Marshall

Chris Uppal coughed up:
A slightly depressing idea has just occurred to me. It may be that
this kind of thinking (which I also see far too often) comes from an
inability to perceive the quality (or lack of it) in code. E.g. if
someone cannot see that one expression is much more readable than
another, then they have no way to gauge "quality" other than by
applying the more-or-less superficial "laws" that they have learned
(presumably by rote) in the past.

I am unable to read French. But -- having been "taught" it at school
(or, more accurately, having been drilled to scrape through the
French exams at
school) -- I can sometimes puzzle out the rough sense of simple
sentences. Given those "talents" there is no way at all that I could
ever tell the difference between good written French (expressive,
articulate, clear, and interesting to read) and bad (dull, obscure,
ambiguous, or banal). I could (rote) learn a few simple tests (how
many words per sentence,
presence/absence of some fixed set of known clichés, etc), but being
effectively blind to it as a language, I could never develop a sense
of the quality that is supposed to be Just Obvious.

I don't know if that /is/ the explanation for the knee-jerk responses
to -- say -- gotos, but I've worked with enough code that was
(apparently) written without any sensitivity to what I would call
quality (fluid, flexible, transparent, and correct), that I suspect
that "quality blindness" isn't all that rare.


Interesting way to put it. This seems entirely congruent to my post. I
still think back on that anti-goto meeting and want to hit something.
 
C

Chris Uppal

Thomas said:
So my pondering is less "is it their fault for rushing" and more "to what
degree would /anything/ have been 'better' had they waited".

Hmm...

One possibility is that they'd have discovered that Unicode isn't 16-bit. I'm
not sure when it first /should/ have been evident that a 16-bit char type
wasn't sufficient, but it was certainly no later than July 1996, when Unicode
2.0.0 was published. (Recall that Sun were intimately involved in Unicode, so
at least /some/ people at Sun would have known what was going on significantly
earlier than that -- though there's no special reason to expect that they'd
have been talking to Gosling, et al.) For comparison, according to Sun's site,
Java was first announced in May '95, and JDK 1.0 was released in January '96.

It's rather unfortunate: the Java designers made an entirely laudable attempt
to get everything (well, most everything) specified clearly and without
"implementation-defined" weasel-words. Not only in order to ensure the
strategic goal of WORA, but also (I believe) out of a simple desire to Do The
Right Thing. The side effect of that was that Java was straight-jacketed very
early in its history. Compare the case of C++, even ignoring the fact that
many aspects of C/C++ semantics are "implementation-defined", the freeze didn't
set in until much later in its history. First there was the series of
incremental changes as Stroustrop released the various versions (all heavily
based on feedback from the previous versions), and then the ANSI/ISO
standardisation process effective re-designated all the earlier versions as
"prototypes". So there were many years of experience with using C++ before it
was frozen by standardisation. For Java, in contrast, the JLS was first
published in August '96.

I don't think it'd be too unreasonable to think of JDK1.1 (released February
'97) as the first "real" Java, so one could look at that for an indication of
what might have been done right if 1.0 had been thought of as a pre-release
with which backwards compatibility wasn't too much of an issue. Some of the
more amateurish bits of the class library might not now be hanging around and
cluttering things up. E.g. InputStream and Date could have been removed or
fixed /properly/.

OTOH, that "amateurish" quality did make Java look a lot simpler -- and that
simplicity was (IIRC) a big part of its early appeal. The more complicated
(and perhaps over-engineered, certainly not /under/-engineered) replacements
might have hindered the initial takeup of Java.

(Just to get this back on topic: just imagine if the first public version of
Java had come out with the current implementation of generics -- Sun would have
been laughed off the face of the earth ;-)

-- chris
 
T

Thomas G. Marshall

Chris Uppal coughed up:
Hmm...

One possibility is that they'd have discovered that Unicode isn't
16-bit. I'm not sure when it first /should/ have been evident that a
16-bit char type wasn't sufficient, but it was certainly no later
than July 1996, when Unicode
2.0.0 was published. (Recall that Sun were intimately involved in
Unicode, so at least /some/ people at Sun would have known what was
going on significantly earlier than that -- though there's no special
reason to expect that they'd have been talking to Gosling, et al.)
For comparison, according to Sun's site, Java was first announced in
May '95, and JDK 1.0 was released in January '96.

It's rather unfortunate: the Java designers made an entirely laudable
attempt to get everything (well, most everything) specified clearly
and without "implementation-defined" weasel-words. Not only in order
to ensure the strategic goal of WORA, but also (I believe) out of a
simple desire to Do The Right Thing. The side effect of that was
that Java was straight-jacketed very early in its history. Compare
the case of C++, even ignoring the fact that many aspects of C/C++
semantics are "implementation-defined", the freeze didn't set in
until much later in its history. First there was the series of
incremental changes as Stroustrop released the various versions (all
heavily based on feedback from the previous versions), and then the
ANSI/ISO standardisation process effective re-designated all the
earlier versions as "prototypes". So there were many years of
experience with using C++ before it was frozen by standardisation.
For Java, in contrast, the JLS was first published in August '96.

I don't think it'd be too unreasonable to think of JDK1.1 (released
February '97) as the first "real" Java, so one could look at that for
an indication of what might have been done right if 1.0 had been
thought of as a pre-release with which backwards compatibility wasn't
too much of an issue. Some of the more amateurish bits of the class
library might not now be hanging around and cluttering things up.
E.g. InputStream and Date could have been removed or fixed /properly/.

OTOH, that "amateurish" quality did make Java look a lot simpler --
and that simplicity was (IIRC) a big part of its early appeal. The
more complicated (and perhaps over-engineered, certainly not
/under/-engineered) replacements might have hindered the initial
takeup of Java.

(Just to get this back on topic: just imagine if the first public
version of Java had come out with the current implementation of
generics -- Sun would have been laughed off the face of the earth ;-)


They would have been laughed off the face of the earth (certainly) but only
because it would have been viewed as a botched attempt at a full run-time
generics. Of course, sun /never/ would have opted for this erasure hoo-hah,
given that they would have had no backward compatibility straightjacket.

My suspicion in all of this is that sun very nearly got as much "right" as
they possibly could have given the era. My question is maybe more what did
they ignore that was obvious.

There were a /lot/ of things that didn't get stable until later. AWT, for
instance was not stable (IMO) until 1.1.7, when (again IMO) everything
somehow /came together/. I sort of view 1.1.7 as 3D block letters
descending from the sky with a light on it and the musical sound "whaaaaaa",
while below it on the ground are all the smoking burned remnants of prior
revs clearly struck by lightning.

FWIW and ICBW, but I /definitely/ think that there must have been folks
within sun begging for a fully thought out reflection capability in 1.0, to
allow programmatic type-level introspection. Much earlier on many might
have wanted formalized collections, I'm also betting there were factions
wishing to meld access to them using array syntax. Very early on the nio
business might have seemed an obvious replacement for the slow endlessly
stacked decorator pattern io, which I'm sure was an OO-purist requirement.
And certainly there were at least a couple cringing at naming the thing
Null/Pointer/Exception. :)

Few of my many guesses.
 
T

Tim Tyler

Eric Sosman said:
The value proposition of generics, it seems to me, lies
purely in the fact that they make some kinds of mistakes
diagnosable by the compiler instead of by the JVM.
Every study I've ever heard of concludes that the cost of a bug
increases the longer it remains in the code, so a bug found
by the compiler should cost less than a bug found by testing
(or *not* found by testing ...).

I don't think those studies were performed by fans of smalltalk -
or other dynamic languages.

Those guys say - in a nutshell - that peppering your code with type
information typically slows down development, makes refactoring
harder, and reduces code reabability - while the benefits of
finding bugs at compile time are much over-rated - since an
intelligent lint prorgam can often infer types anyway - and
the bugs type checking catches are generally trivial bugs
which are easily caught by unit tests anyway.

That's not the whole story, but there's a lot of truth in
what these guys say - especially when engaging in activities
such as RAD, prototyping or debugging - e.g. see:

``Smalltalk v. Java: Which is More Productive?
A Java Developer Answers the Question''

- http://www.whysmalltalk.com/articles/raab/productivity.htm

As essentially a rather static language, Java needed generics.

However - IMO - as a rather static language, Java places itself
aside from the mainstream of future language development.

My expectation is that future mainstream programming languages
will offer both static and dynamic features - with the latter
being used for prototyping, RAD work and interactive debugging -
with the former will be used for building libraries and basic
interfaces.
 
T

Tim Tyler

Bent C Dalager said:
Good or bad code is clearly not determinable by the language features
used. Or, indeed, the language used.

If this is true in general, then it shouldn't be possible to construct
a programming language that forces you to write "bad" code. I'd like
to see you write anything beyond a trivial program in Intercal and be
able to call the result "good code." :)

In fact, even a trivial program would be impressive.

Intercal is a programming language deliberately designed to be
idiotic. [...]

http://www.catb.org/~esr/intercal/

See also:

http://c2.com/cgi/wiki?WhitespaceLanguage
http://www.madore.org/~david/programs/unlambda/
http://www.muppetlabs.com/~breadbox/bf/

Those programmers need to get girlfriends ;-)
 
T

Tim Tyler

Chris Uppal said:
David Blickstein wrote:

I don't think that generics have introduced a new class of /bugs/ have they ?

``Generics gotchas''

``Generic types, added in JDK 5.0, are a significant enhancement to type
safety in the Java language. However, some aspects of generics may seem
confusing, or even downright bizarre, to first-time users. In this
month's Java theory and practice, Brian Goetz examines the common
pitfalls that ensnare first-time users of generics. [...]''

- http://www-106.ibm.com/developerworks/java/library/j-jtp01255.html
 
T

Tim Tyler

Yes, and that's not 100% good. If you believe thinking
about and specifying the types of variables is a good
thing (you should!), then the following declaration is not
so good.

Map personnel = new TreeMap();

Being *forced* to specify the types of variables is /not/ a
good thing - as I'm sure the many users of Smalltalk, Python,
PHP, Ruby, Objective C and Perl will attest.
 
T

Tim Tyler

Thomas G. Marshall said:
Chris Uppal coughed up:

Oh man. Nothing worse then when someone's on to you. :)

Actually, no. I've been trying to /not/ go down that route. In this
particular case though, there is a huge disagreement about what "strong"
typing really means, and if there's a way to discuss that /without/
making a DTL/STL argument, then I'm for it.

http://c2.com/cgi/wiki?StronglyTyped

....and...

http://c2.com/cgi/wiki?WeaklyTyped

....seem to agree about that - though maybe citing a Wiki pages to prove
that a concept is not universally agreed upon is not a great argument ;-)

I can't see any support for your notion that strong typing and dynamic
typing don't mix, though - indeed, I'd say the exact opposite - e.g.:

``Most untyped [i.e. DynamicallyTyped] languages are, by necessity,
completely safe (e.g., LISP). Otherwise, programming would be too
frustrating in the absence of both CompileTime and run time checks.''

- http://c2.com/cgi/wiki?StronglyTypedWithoutLoopholes
 
D

David Blickstein

You'll need to explain this part a little better. I'm not sure: you started
with the problem with my enum example, and then followed with the advantage
of enumerations.

The simplest explanation is in your example, it wasn't easy to derive that
what was being done was an enumeration.

As someone else mentioned, simple common programming concepts deserve direct
support from the language even if all it provides is a little syntactic
sugar. The justification being is that the syntax makes it clear that an
enumeration is being used.

If you think about it, take any two languages that provide a Turing machine.
You "can" implement the same program in either of them. What mostly makes
them different is how efficiently the algorithm is expressed/exposed via the
language syntax.
 
D

David Blickstein

I am happy to call Java type system "strong", because it doesn't contain
any
escape hatches that permit me to circumvent its checking[*].

One of my favorite quotes from Peter van der Linden's "Expert C" book (which
is sorta to C what Scott Meyers "Defective C++" book is to C++) goes
something like:

"To a C programmer, 'strong typing' means banging on the keyboard"

:)
 
T

Thomas G. Marshall

David Blickstein coughed up:
The simplest explanation is in your example, it wasn't easy to derive
that what was being done was an enumeration.

As someone else mentioned, simple common programming concepts deserve
direct support from the language even if all it provides is a little
syntactic sugar. The justification being is that the syntax makes it
clear that an enumeration is being used.

If you think about it, take any two languages that provide a Turing
machine. You "can" implement the same program in either of them.
What mostly makes them different is how efficiently the algorithm is
expressed/exposed via the language syntax.


I see it as /very/ clear what it is. Besides, my example would be probably
be this:


public class TrafficLiteColor extends AbstractEnum
{
// etc.
}

Which is even more clear. Besides, knowing that an enum is an enum is not
the bottom line. Seeing how it is /used/ is, and that would be, of course,
evident from the code. It does you no good to know that something is an
enum if you don't know how or where it is used.
 
C

Chris Uppal

David said:
If you think about it, take any two languages that provide a Turing
machine. You "can" implement the same program in either of them. What
mostly makes them different is how efficiently the algorithm is
expressed/exposed via the language syntax.

Or how effective the language's syntax is in allowing you to express concepts
and structures transparently /without/ adding special syntax.

Of the front-line programming languages, Java is probably the least supportive
in this respect (Fortran and Cobol may be worse -- I don't know either well
enough to have an opinion -- but they surely can't be /that/ much worse).
Incidentally, this is -- just for once ;-) -- not intended as criticism of
Java, merely an observation about the position that it occupies in the language
design space.

-- chris
 
D

David Blickstein

I see it as /very/ clear what it is. Besides, my example would be probably
be this:


public class TrafficLiteColor extends AbstractEnum
{
// etc.
}

Which is even more clear. Besides, knowing that an enum is an enum is not
the bottom line. Seeing how it is /used/ is, and that would be, of course,
evident from the code.

We just disagree, and some of it is a "where you draw the line on a sliding
scale" difference.

Providing language syntax for enums just makes the declaration more terse.
From where i sit, your example just has a bit of excess and nominally
irrelevant verbage needed for Java to setup the underlying class mechanisms.
It does you no good to know that something is an enum if you don't know
how or where it is used.

My opinion is that knowing it is an enum is the largest part of finding out
"how" it is used.

It tells me that the abstract usage (this is one selection where limited
number of selections are allowed). Not knowing it is an enum, a usage
might appear to be an assignment of a constant value (enumeration values are
NOT constants - they are just typically implemented that way), or a
selection of a particular class object.

I think the only thing that really tells me otherwise in your example is the
naming convention.

Again, just differences of reasonable opinion here.
 
M

Mike Schilling

Chris Uppal said:
Or how effective the language's syntax is in allowing you to express
concepts
and structures transparently /without/ adding special syntax.

Of the front-line programming languages, Java is probably the least
supportive
in this respect (Fortran and Cobol may be worse -- I don't know either
well
enough to have an opinion -- but they surely can't be /that/ much worse).

FORTRAN-77 is far worse. I don't know the newer languages called FORTRAN.
But C and C++ are also worse, and C# almost identical, so I don't know which
languages you consider "front-line".
 
C

Chris Uppal

Mike said:
FORTRAN-77 is far worse. I don't know the newer languages called FORTRAN.
But C and C++ are also worse, and C# almost identical, so I don't know
which languages you consider "front-line".

C and C++ both have macros (albeit kinda stunted). C++ has operator
overloading. Both provide means by which programmers can express the meaning
of the code more directly/transparently than would be possible in the "base"
language. I.e. a way of stating directly what concept is involved rather than
relying of the reader recognising an idiom.

My understanding of David's position is that when an idiom can be converted
into syntax, there's a gain in transparency in the language. It's a POV that I
would agree with, except that adding new syntax for each idiom add complexity
too, and I don't like that. So I wanted to emphasise that there was an
alternative -- to the extent that the language design allows it, it may be
possible to express concepts directly without relying on the reader to
recognise idioms but without requiring a syntax extension.

Java -- as I said -- has basically no abilities in that direction[*]. C and
C++ have /some/ abilities (easily abused, I agree) in that direction.
LISP/Scheme is /packed/ with that kind of ability, and so in a very different
way is Smalltalk (and yes, I do consider both of those to be "front-line" -- I
understand that you may not agree).

([*] except insofar as OO itself can be thought of as a kind of language
extension mechanism -- viewing each class library as a small "language" for the
corresponding domain.)

-- chris
 
D

David Blickstein

My understanding of David's position is that when an idiom can be converted
into syntax, there's a gain in transparency in the language. It's a POV that I
would agree with, except that adding new syntax for each idiom add complexity
too, and I don't like that.
So I wanted to emphasise that there was an alternative...

Do you like the "for" statement? Because for the most part, it is
unnecessary once you have a "while" statement.

I'm presuming that your position isn't that a feature shouldn't be added if
it's already possible to code something equivalent - an "alternative". If
that was the case, once you have a complete Turning machine, all subsequent
language additions are bad.

So what I don't understand is what Uppal language inclusion test does
"enums" fail but "for" pass?
Java -- as I said -- has basically no abilities in that direction[*].

I think the "for" statement is a counter-example.
 
T

Thomas G. Marshall

David Blickstein coughed up:
My understanding of David's position is that when an idiom can be
converted into syntax, there's a gain in transparency in the
language. It's a POV that I would agree with, except that adding
new syntax for each idiom add complexity too, and I don't like that.
So I wanted to emphasise that there was an alternative...

Do you like the "for" statement? Because for the most part, it is
unnecessary once you have a "while" statement.

I'm presuming that your position isn't that a feature shouldn't be
added if it's already possible to code something equivalent - an
"alternative". If that was the case, once you have a complete
Turning machine, all subsequent language additions are bad.

So what I don't understand is what Uppal language inclusion test does
"enums" fail but "for" pass?
Java -- as I said -- has basically no abilities in that direction[*].

I think the "for" statement is a counter-example.


Hmmmm....

I think that this is impossible to judge using the single adjective of
"alternative". This is missing the metric of "complexity".

To that limited extent, I am glad that there are enums, but *only* because
so many folk just never even /thought/ through how to make them easily
type-safe, which I find so *utterly* irritating. I actually worked with a
couple of guys that built their own enum class in such a way that the enums
were always of the type Enum. Jesus. I consider my example to be easy.
And sun was a huge abuser of unsafe "enums".

I was reacting mostly because you stated that type safe enums were not
possible, which you clarified to mean "not easily possible". The
disagreement now is (as you know) what is easy, and what is obvious by
syntax alone.

I would argue, that my example is both easy, and as obvious as nearly any
other class. Remember, that the class

ArrayList

only makes immediate sense because of its name. The example I gave:

public class TrafficColorEnum
{
public static final RED = new TrafficColorEnum();
public static final GREEN = new TrafficColorEnum();
public static final YELLOW = new TrafficColorEnum();
}

is no different IMO. {shrug}
 
B

beliavsky

Mike Schilling wrote:

worse).

FORTRAN-77 is far worse. I don't know the newer languages called FORTRAN.
But C and C++ are also worse, and C# almost identical, so I don't know which
languages you consider "front-line".

Fortran 90 has user-defined types with operator overloading, and
Fortran 95 added elemental functions, which can take scalars or
multidimensional arrays as arguments. Fortran 2003 adds classes with
inheritance, but it does not have the support for generic programming
(templates and the Standard Library) of C++, although it has better
built-in array handling.
 
T

Thomas G. Marshall

(e-mail address removed) coughed up:
Mike Schilling wrote:



Fortran 90 has user-defined types with operator overloading, and
Fortran 95 added elemental functions, which can take scalars or
multidimensional arrays as arguments. Fortran 2003 adds classes with
inheritance, but it does not have the support for generic programming
(templates and the Standard Library) of C++, although it has better
built-in array handling.


Interesting.

I'm beginning to wonder if the biggest thing that fortran has going against
itself is its name....
 

Ask a Question

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

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

Ask a Question

Similar Threads

Generics ? 14
can this be done with generics? 32
More Generics warnings. 5
stupid generics 38
Generic generics help 7
Java generics limitations? 9
Generics and for each 12
Help on java generics 18

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,173
Latest member
GeraldReund
Top