light weight types

M

markspace

Alessio said:
On the other hand, you could write var x = new HashMap<String,
List<MyThing>>() instead of
HashMap<String, List<MyThing>> x = new HashMap<String, List<MyThing>>
() which imho would only make the code clearer.

Soon (Java 7), you'll be able to write:

HashMap<String, List<MyThing>> x = new HashMap<>();

Or even:

Map<String, List<MyThing>> x = new HashMap<>();

Which is more useful, imo.
 
L

Lew

Michal said:
Sorry - it looks like it is just NetBeans not showing any warning.

Then you should turn on the warning in NetBeans.

Menu: Tools / Options / Editor / Hints tab
 
R

Robert Klemme

And so natural that it would not add to the complexity of
the language.

I am not sure I can follow you here: you add a new feature to the type
system and yet claim that it does not increase the complexity of the
language. I do not believe this. We could argue about the level of
complication that this adds but it's certainly larger than zero.

Kind regards

robert
 
R

Roedy Green

(And yet the simple things
like unsigned math

A ubyte type could be added without even changing the JVM. The
compiler could even just mindlessly add in & 0xff after every load.
There might be a problem finding bits to accommodate ubyte in the byte
codes.

for a uint, it not that onerous to use long and &0xffffffff; manually

for a ulong you truly need unsigned arithmetic. But one extra bit in
64 is not that big a prize.

My thinking is, ubyte is the main thing to go for. The current signed
bytes are too error prone, since 99% of the time you want ubyte.

--
Roedy Green Canadian Mind Products
http://mindprod.com

When you can’t find a bug, you are probably looking in the wrong place. When you can’t find your glasses, you don’t keep scanning the same spot because you are convinced that is where you left them.
~ Roedy
 
R

Roedy Green

1. Option types
Whatever the name of the feature - I'd like to be able to mark a variable as
not null (I would actually prefer to mark variables as nullable but that
would not be backwards compatible). And I don't think adnotations are
enough.

IntelliJ Idea has as system where you can mark parameters and return
results as @Nullable or @NotNull.

You have to provide a special annotations.jar file to the compiler.

@Nullable means the value may potentially be null, &NotNull means it
may not.

I understand the intent, but I don't understand how they work. It may
be they are only examined during lint (code inspector).

--
Roedy Green Canadian Mind Products
http://mindprod.com

When you can’t find a bug, you are probably looking in the wrong place. When you can’t find your glasses, you don’t keep scanning the same spot because you are convinced that is where you left them.
~ Roedy
 
R

Roedy Green

Whatever the name of the feature - I'd like to be able to mark a variable as
not null (I would actually prefer to mark variables as nullable but that
would not be backwards compatible). And I don't think adnotations are
enough.

The feature of the Nice language most intriguing to Java programmers
is it gets rid of the NullPointerExceptions by determining at compile
time if they could happen.

This sounds impossible to me. I can see getting rid of some, but not
all, unless you make programmers do explicit null checks any place
they could cause trouble.

http://nice.sourceforge.net/index.html

--
Roedy Green Canadian Mind Products
http://mindprod.com

When you can’t find a bug, you are probably looking in the wrong place. When you can’t find your glasses, you don’t keep scanning the same spot because you are convinced that is where you left them.
~ Roedy
 
R

Roedy Green

Roedy, Sounds like Pascal Type declarations, which is one of the
things I really miss in Java.

Jim

In Abundance, my home brew language, I had a bounded int type, with an
enforced lower and upper bound. The bounds were used to generate
keying prompts and validation.

I first developed a lust for this light-weight type feature writing a
crash-proof disk-based cached Btree implementation back in the 70s,
where there were a bewildering number of arrays and subscripts. The
error I kept making was using the wrong subscript with a given array.
I wanted a way to tie subscripts and arrays so they had to be used
together, with any inconsistencies detected at compile time. Another
way of thinking of this is my index variable was in ordinary int, but
of a special type that could only be used to index certain arrays.

Earlier, circa 1973, I was keen on units of measure. Canada was in
the process of converting Imperial measure to metric. Engineering
computer programs were a hash of units, and bugs were frequent from
mismatches. I figured if every value were given a unit of measure,
the compiler could guarantee consistency, and even apply guaranteed
correct conversion constants. It could even check dimension
consistency in engineering formulae. e.g. speed is length/time
dimensionality. You could not assign a length/time^2 expression to
it.

I recall my delight at learning about dimensionality in high school.
It could even tell you the form some physics equation had to take
before you had even done any analysis of the physics.


..


--
Roedy Green Canadian Mind Products
http://mindprod.com

When you can’t find a bug, you are probably looking in the wrong place. When you can’t find your glasses, you don’t keep scanning the same spot because you are convinced that is where you left them.
~ Roedy
 
R

Roedy Green

I first developed a lust for this light-weight type

In scientific/engineering, you can't afford the overhead of a
full-blown Java type. You want something that prevents mismatch
errors, but that does everything at compile time, much like generics.
For that, you are willing to give up a lot e.g. aggregates,
inheritance. You want the same code generated that if you had used
primitives instead of types.

Perhaps another way to look at this is how could you implement a final
Java type containing but one primitive in a highly efficient way?
Perhaps it could be autounboxed/boxed.


--
Roedy Green Canadian Mind Products
http://mindprod.com

When you can’t find a bug, you are probably looking in the wrong place. When you can’t find your glasses, you don’t keep scanning the same spot because you are convinced that is where you left them.
~ Roedy
 
R

Roedy Green

I could see the use of something like this in Java, but I am concerned
about adding another complex syntax to the language.

Java is obviously not the final solution. How fast do we evolve, and
do we do it by modifying Java or starting over.

I think the next big round of progress will come when we abandon the
notion that computer languages are conceptualised as linear ASCII text
files.

I think it is time to think of programs as directed graphs, displayed
with filters to show you only what is of immediate interest.

The problems we have are being overwhelmed by verbose detail and
inscrutably complex syntax (i.e. generics). We have to think about
hiding what is not relevant for now, as a fundamental part of
"language" design.

how can we add features for one group of programmers without baffling
those who don't need it?

Just as class libraries have forced programmers to give up doing
HashMaps "their way", this same standardisation process needs to
continue, so that AI/class libraries take over more and more of the
fussy details, in particular screen layouts, data entry and data
validation.

See http://mindprod.com/project/scid.html

Another metaphor is the Google Earth map where you can zoom in to
various levels of detail, or zoom out to see the whole thing.
--
Roedy Green Canadian Mind Products
http://mindprod.com

When you can’t find a bug, you are probably looking in the wrong place. When you can’t find your glasses, you don’t keep scanning the same spot because you are convinced that is where you left them.
~ Roedy
 
L

Lew

Roedy said:
The problems we have are being overwhelmed by verbose detail and
inscrutably complex syntax (i.e. generics). We have to think about

Generics is not inscrutable. With a little study, as little as reading the
short free chapter on generics from Bloch's /Effective Java/, it's utterly
scrutable.

Not a good example for what is otherwise a decent point.
 
D

Dave Searles

Roedy said:
Java is obviously not the final solution. How fast do we evolve, and
do we do it by modifying Java or starting over.

I think the next big round of progress will come when we abandon the
notion that computer languages are conceptualised as linear ASCII text
files.

To some extent, that's already happened. It's called "Lisp". :)
 
J

Jeff Higgins

John said:
Thank you for responding. I'm not sufficiently familiar with the process
to understand the import of the discussion you cited. The measure
package was moved to javax.measure in anticipation of standardization as
part of JSR-275. Failing that, the code still seems useful. Is there
some reason to be wary?

The JSR process is opaque.
I would rather have seen another development process chosen,
and the measure.* packages remain in the jscience namespace.
I am not certain what benefit the API of the measure.*
packages accrue from becoming a 'standard technical specification'.
The code is useful, available, and liberally licensed.
The JSR process is opaque.
 
R

Roedy Green

I think it is time to think of programs as directed graphs, displayed
with filters to show you only what is of immediate interest.

Word processing got stuck in a rut for a while, with markup languages
like Tek and Wordstar command codes. Once we decided the internal
format was no concern of the users, it greatly simplified the process
of creating documents.

We need to do something similar for programming.
--
Roedy Green Canadian Mind Products
http://mindprod.com

When you can’t find a bug, you are probably looking in the wrong place. When you can’t find your glasses, you don’t keep scanning the same spot because you are convinced that is where you left them.
~ Roedy
 
R

Roedy Green

Generics is not inscrutable. With a little study, as little as reading the
short free chapter on generics from Bloch's /Effective Java/, it's utterly
scrutable.

Can you really explain the difference between
<?> vs <Dog> vs <? extends Dog> vs <E extends Dog> vs <? super T>
in a few paragraphs so that at least 50% of your readers will follow?

If you want to make a stab at it, I would love to cannibalise your
work for the Java glossary Generics entry.

The best I have seen has been explanations of what a few specific
examples do. When you find people resorting to examples to explain,
You know it is difficult material.

I guess it depends on your base point. Generics are scrutable relative
to Revelation, but inscrutable compared say with a typical explanation
of parameter passing.

I found generics the most confusing feature of Java. Look how many
posts there are on them, quite often coming from relatively
experienced programmers.

You might measure a feature in a language by the power it gives you
divided by the effort you need to expend to learn it and use it.
Generics have a fairly low payback number. I don't know if the
complexity was unavoidable, or as a side effect of insisting on type
erasure.

Generics lack the elegance of other Java features. The syntax is ad
hoc, unshaved, irregular, Perlish, unfinished.

With most features, you have and ah ha moment, and all falls into
place. Everything is as it should be. It could be no other plausible
way. You "grok" them in fullness, and no longer need to read a manual
to write code. Generics don't do that, at least not yet.

--
Roedy Green Canadian Mind Products
http://mindprod.com

When you can’t find a bug, you are probably looking in the wrong place. When you can’t find your glasses, you don’t keep scanning the same spot because you are convinced that is where you left them.
~ Roedy
 
J

Joshua Cranmer

Can you really explain the difference between
<?> vs<Dog> vs<? extends Dog> vs<E extends Dog> vs<? super T>
in a few paragraphs so that at least 50% of your readers will follow?

It helps to explain generics by thinking in terms of containers--most
generified types are containers in some form or other.

Generified types can be declared thusly:

public class Container<T> {}

The `T' represents a type. The implementer of Container has no idea what
type it is, it's just some type, any type. Since we don't know what it
is, all we can guarantee is that it is an Object of some type (all
non-primitive types are a subclass of Object, and generics don't use
primitive types), so wherever `T' is found in the implementation, you
can mentally replace it with `Object' for the same effect.

Sometimes, though, we don't want to let people include any old object.
To do this, we declare an upper bound on the type like so:
public class Container<T extends Number> {}

Now only numeric types can be stored in the container. Also, since we
know that any given value of `T' has to be a subclass of Number in some
fashion, we can replace it with `Number' instead of `Object'.

You can also specify a /lower/ bound on the type, by specifying `super'
instead of `extends'. The rationale behind this will be made clear
slightly later.

To use generics, you merely have to replace the appropriate parameter
with your class. So an integer container is declared as type
`Container<Integer>' (again primitive types are not valid here; this is
due to implementation necessities. But don't forget that Java 5+
autoboxes primitive types).

An important fact to realize is that subtyping of generic types isn't
quite what would be expected at first: if A is a subclass of B,
Container<A> is not a subtype of Container<B>. Remember that a container
stores it type: you can store any B into a Container<B>, so being able
to cast from Container<A> to Container<B> means you can put a B into the
Container<A>.

The way around this is to state that you don't know what's contained
inside in the container. We do this with the type `?' (also known as the
wildcard type): Container<?> stores /something/, but we don't know what.
Since Container<A> stores objects of type `A', it stores objects of any
type, so it is a subtype of (and thus convertible to) Container<?>.
Conversely, since we don't know what type a Container<?> holds, we can't
store stuff inside the container.

However, since we know that all Containers must store Objects, we can
treat whatever is in the Container as an Object. In effect, the wildcard
turns the Container into a read-only object: you can't write into
Container<?>, but you can read from it. This is internally enforced by
the special subtyping rules of generic objects; the exact mechanisms
require some mathematical theory that I will not delve in here.

Similarly to how we limited the storage type of a container with the
`extends Number' relationship, we can limit the type of a wildcard. A
type `Container<? extends Number>' indicates that the object stores
something that is at least of type Number. Once again, that means that
instead of viewing it as containing something that is at least an
Object, we can see it as containing something that is at least a Number.

Types can also be recursive. A recursive type is something of the form
class Foo<T extends Foo<T>>. You generally subclass or implement
interfaces of these form in the fashion class Bar extends Foo<Bar>. The
purpose of a recursive type is to operate on itself in some fashion:
think of Comparable's compareTo method. Classes implementing Comparable
only compare objects of the same class as them, not of other classes
implementing Comparable.

Methods can also be generified. The rationale here is for utility
methods operating on generic container classes. Here is an example of a
generic method definition:
public static <T> T move(Container<T> from, Container<? super T> to);

Here, you also saw an example of the use of the lower bounds. We want to
be able to take an Integer stored in a Container<Integer> and put it
into a Container<Number>. Using upper bounds is also possible here, but
if we were to do that, we'd be given a Number and not an Integer. The
object being moved is already known to be a Number, so we should we
unnecessarily restrict the type of return?

The other main use of lower bounds is in recursive types. Specifying <T
extends A<T>> is generally incorrect: <T extends A<? super T>> is
typically more correct.


How was that?
The best I have seen has been explanations of what a few specific
examples do. When you find people resorting to examples to explain,
You know it is difficult material.

I think that examples are not so much needed to explain, but more to
motivate why the developers did things the way they did. Generics are
actually rather simple once you understand what they actually mean (what
I gave above is roughly how I came to realize their underlying
mechanisms), which explains why some operations that would seemingly be
safe are actually not safe. Well, rare types (mixing raw types and
generics) don't actually make sense in many cases. Suffice to say that I
am personally extremely aggravated that List.class is of type
which makes for some particularly said:
You might measure a feature in a language by the power it gives you
divided by the effort you need to expend to learn it and use it.
Generics have a fairly low payback number. I don't know if the
complexity was unavoidable, or as a side effect of insisting on type
erasure.

I wouldn't say that they have fairly low payback. What they increase
substantially is compile-time type safety. Having spent considerable
amounts of time in languages that have very little compile-time type
safety, trust me when I say that the more the compiler complains to you
about, the better.
Generics lack the elegance of other Java features. The syntax is ad
hoc, unshaved, irregular, Perlish, unfinished.

Actually, the syntax is cribbed from C++ templates. Blame Bjarne Stroustrup.
With most features, you have and ah ha moment, and all falls into
place. Everything is as it should be. It could be no other plausible
way. You "grok" them in fullness, and no longer need to read a manual
to write code. Generics don't do that, at least not yet.

To me, generics has had that moment. The best way I can think to explain
them is to think of a generic type as containing an object of some type;
wildcard objects are ways of saying that you don't know what it
contains, but you may have some information.
 
L

Lew

Roedy said:
Can you really explain the difference between
<?> vs <Dog> vs <? extends Dog> vs <E extends Dog> vs <? super T>
in a few paragraphs so that at least 50% of your readers will follow?

I don't need to. Joshua Bloch and Brian Goetz have already done that.

Read their stuff.

Really, read it.
 
L

Lew

Roedy said:
Generics lack the elegance of other Java features. The syntax is ad
hoc, unshaved, irregular, Perlish, unfinished.

Generics syntax is just fine, taken for what it is. Most people's trouble
lies in their attempt to make it something other than what it is.

I'm not saying generics is the easiest thing in the universe - it has to
express type analysis, and we programmers are not most of us used to doing
type analysis. Unfamiliarity makes it seem even harder. But it's not the
ridiculously insurmountable pinnacle you're trying to claim it is.

Generics syntax is a declarative calculus for type assertions. As such it is
very, very powerful. I also have observed that generics do not add to the
complexity of type analysis - it's type analysis that is hard.

Generics has close to a half dozen syntactic elements:
<>
?
extends
super
T

When you say

static <T> void sort( List<T> list, Comparator<? super T> c )

you are simply declaring that the 'compareTo' method can handle some supertype
of T, and therefore can compare T as well.

Where people run into trouble is having two different <? extends Foo>
expressions and expecting one "some subtype of Foo" to be the same as the
other "some subtype of Foo" when the two captures express no such connection.

And also when they don't read the explanatory material.
With most features, you have and ah ha moment, and all falls into
place. Everything is as it should be. It could be no other plausible
way. You "grok" them in fullness, and no longer need to read a manual
to write code. Generics don't do that, at least not yet.

I had that "ah-hah" moment. I'm sorry that you haven't, yet. Read the
materials I keep referencing and you should have it, too. At the very least
you'll develop useful rules of thumb that make it possible to use generics.

I've watched several other programmers approach generics for the first time
and get that "ah-hah" also, usually within a few days of reading the
recommended materials if they're experienced Java programmers. So I'm not
claiming that I'm anything special here.

<http://java.sun.com/docs/books/effective/> - free chapter on generics
<http://www.ibm.com/developerworks/java/library/j-jtp04298.html>
<http://www.ibm.com/developerworks/java/library/j-jtp07018.html>

Read, and say, "Ah-hah!"
 
L

Lew

Joshua said:
Types can also be recursive. A recursive type is something of the form
class Foo<T extends Foo<T>>. You generally subclass or implement
interfaces of these form in the fashion class Bar extends Foo<Bar>. The
purpose of a recursive type is to operate on itself in some fashion:
think of Comparable's compareTo method. Classes implementing Comparable
only compare objects of the same class as them, not of other classes
implementing Comparable.

However, be careful not to think of the generic parameter declaration as any
kind of operation. "<T extends Foo<T>>" is not an operation. It is an
assertion about the limitations on the type.

It was this shift from procedural thinking to declarative thinking that made
generics make sense to me.
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top