Tightening the type system

R

Roedy Green

Java has a goofy two-tier typing system.

1. run time using inheritance.

2. compile time using generics.

yet for primitive, there is no typing at all.

It is easy for example to reverse two int arguments to a method, one
an offset in pixels and the other an index to an array.

Perhaps the next stage is a compile time typing system for primitives.

the stage after that is to start over with a unified type system that
works with the same syntax the same for everything, at least from the
programmers' perspective.

One way of looking at a typing system for primitives is that you are
assigning units of measure. That opens to door to automatic
conversion, e.g. from US to metric.

That would prevent all kinds of error that untyped ints allow.

IT would add no run time overhead.


so I might write something like this:

oranges o = 7;

apples a = 2;

apples c = 2* a; // legal

apples c = o + a; // illegal

pick( a );
pick( o );

where oranges and applets are subclasses of fruit.

pick ( fruit x )


You could invent a set of nesting names, just like classes.

The type system would also help in IDEs. Once you wrote the name of a
method invocation there would be very few possible ways of completing
it. You could write a lot of code by multiple choice rather than by
typing.


--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
H

Hemal Pandya

Roedy said:
Java has a goofy two-tier typing system.

1. run time using inheritance.

2. compile time using generics.

yet for primitive, there is no typing at all.

A boolean cannot be implicitly converted to an int. You do not consider
that an aspect of the type system?
It is easy for example to reverse two int arguments to a method, one
an offset in pixels and the other an index to an array.

But this problem exists for any type! It is just as easy to reverse to
String arguments to a method. Or for that matter any user defined type.

Named parameters are one solution to address this particular problem.
I am reminded of Bjarne Stroustrup's argument against including them in
C++; but I am sure you already know about that.

I am pretty sure I am missing something. Wonder what.
 
A

Andrea Desole

Roedy said:
Java has a goofy two-tier typing system.

1. run time using inheritance.

2. compile time using generics.

yet for primitive, there is no typing at all.

It is easy for example to reverse two int arguments to a method, one
an offset in pixels and the other an index to an array.

Perhaps the next stage is a compile time typing system for primitives.

are you talking about a typedef for java?
 
H

Hemal Pandya

Roedy said:
are you talking about a typedef for java?

I thought about typedef, but a little test showed that they have
structure equivalence, not name equivalence. So one type typedef'd to
two different names will still allow implicit conversion from one to
the other. Perhaps a typedef with name-equivalence is what Roedy is
looking for.

I have in past used extension, without adding any fields or methods in
the subclass, just for differentiating in this manner.
 
A

Andrea Desole

Hemal said:
I thought about typedef, but a little test showed that they have
structure equivalence, not name equivalence. So one type typedef'd to
two different names will still allow implicit conversion from one to
the other. Perhaps a typedef with name-equivalence is what Roedy is
looking for.

yes, typedef is a bit loose. Still, the post really reminded me of
typedef. Maybe a bit stricter
 
B

Boudewijn Dijkstra

[...]

so I might write something like this:

oranges o = 7;
apples a = 2;
apples c = 2* a; // legal
apples c = o + a; // illegal
pick( a );
pick( o );

where oranges and applets are subclasses of fruit.

pick ( fruit x )

Or alternatively:

int<Orange> o = 7;
int<Apple> a = 2;
int<Apple> c1 = 2 * a; // legal
int<Apple> c2 = o + a; // illegal
pick( a );
pick( o );
pick ( int<? extends Fruit> x )

Where the type parameters are classes that give information on the type.
Something like:

class Fruit extends java.lang.reflect.IntegerType
{
public Fruit() {}
public int getMinimum() {
return 0;
}
public String getFriendlyUnit() {
return "Number of pieces of fruit";
}
}
class Apple extends Fruit
{
public Apple() {}
public String getFriendlyUnit() {
return "Number of apples";
}
}

These classes would then (normally) only be used at compile time.
 
C

Chris Riesbeck

Roedy Green said:
It is easy for example to reverse two int arguments to a method, one
an offset in pixels and the other an index to an array.

Perhaps the next stage is a compile time typing system for primitives.

the stage after that is to start over with a unified type system that
works with the same syntax the same for everything, at least from the
programmers' perspective.

One way of looking at a typing system for primitives is that you are
assigning units of measure. That opens to door to automatic
conversion, e.g. from US to metric.

That would prevent all kinds of error that untyped ints allow.

IT would add no run time overhead.

As noted in another post, such errors can happen with
non-primitive types, e.g., a function that takes two
Strings or two Employees.

A complementary approach with no run-time overhead is
keyword arguments. When calling a method, you specify the
role of each argument. This helps even in cases when
the types are identical, e.g.,

makePoint(x : 2, y : 3)

which is the same as

makePoint(y : 3, x : 2)

or some such syntax. It doesn't prevent you from
passing the wrong things, but you have to be actively
stupid about it.
 
R

Roedy Green

Perhaps a typedef with name-equivalence is what Roedy is
looking for.

I am looking for something stronger. I want it to catch you adding
apples to oranges even though both internally and handled with an int.

Further, I think the compiler should catch you assigning something
measured in lines to something measured in pixels. It could catch
degree F vs degree C errors.

I first ran into the problem writing a Pascal program years ago to
implement a super fast, crash proof Btree. There were several arrays
and many indexes. Variables were associated with an array. Yet the
compiler could not check that I used a variable of the wrong "type" to
index an array.

I attacked the problem in my own language by giving each array its own
primary index and naming it the same as the array.

In Java I would propose an Ada-ish solution. You can delare a new unit
of measure, e.g. the "band" which in what the index of an array spans.
Then you declare your arrays to be indexed by band and your indexers
to be of band type. You can the further put an assertion on the band
type for range something like an arrayindex out of bounds that
constrains the indexers, but not so strongly as you would using them
as arrayindexes.

I think though what we are going to get is something more like Eiffel.
Classified ints will look much like classes to the programmer, but are
implemented like primitives. Instead of a pointer to the data, the
data itself will be embedded in a referencing class. This would allow,
for example, a more efficient representation of complex numbers.

What I was proposing, since it is pure compile time, could be
implemented with an @units (for units of measure) javaDoc tag
on variables. The IDE could check it long before the compiler even
saw the code.

In any case it is great documentation. In reading other people's code,
figuring out the units of measure consumes a lot of time. My bitch is
people who don't document whether time is in seconds, milliseconds,
microseconds, nanoseconds, ticks, minutes etc. especially when they
use all those different units of measure in the same package.



--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
R

Roedy Green

As noted in another post, such errors can happen with
non-primitive types, e.g., a function that takes two
Strings or two Employees.

It is the same problem in disguise. Java's fundamental type system is
really designed for to keep separate things that have different
physical structure. It muddles together all things that can physically
be represented by an int or String.


If you could subclass primitives or subclass finals, but only for the
purpose of adding additional type constraints, not adding fields or
functionality, that might let you do something like this:



String<Employee> e = "Peter Pollen";

String<PostalCode> p = "V5N 2W5";


Now you can declare a method

sendLetter( String<Employee> employee, String<PostalCode> postalCode
);


If you wrote sendLetter( e, p); it works
If you wrote sendLetter( p, e); that would trigger a compile time type
violation.

You are more likely to get the type declaration right that parameter
orderings right.

The problem is if Sun added a <T> to String, all untyped uses would
generate an error.



--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
G

Gordon Beaton

I am looking for something stronger. I want it to catch you adding
apples to oranges even though both internally and handled with an int.

Further, I think the compiler should catch you assigning something
measured in lines to something measured in pixels. It could catch
degree F vs degree C errors.

You want Ada.

/gordon
 
H

Hemal Pandya

Perhaps a typedef with name-equivalence is what Roedy is
looking for.

I am looking for something stronger. I want it to catch you adding
apples to oranges even though both internally and handled with an int.

Further, I think the compiler should catch you assigning something
measured in lines to something measured in pixels. It could catch
degree F vs degree C errors.[/QUOTE]

I would still want the liberty to assign pixels to lines once in a
while.
I first ran into the problem writing a Pascal program years ago to
implement a super fast, crash proof Btree. There were several arrays
and many indexes. Variables were associated with an array. Yet the
compiler could not check that I used a variable of the wrong "type" to
index an array.

In Pascal you should be able to give different type names to ranges of
integers and use those as the index type for the array. I can't recall
the syntax right now.
I attacked the problem in my own language by giving each array its own
primary index and naming it the same as the array.

Its own primary index or index type?

As another post suggest maybe Ada is the answer. But I am sure you want
this along with all the flexibility of Java.
 
S

Stefan Schulz

If you could subclass primitives or subclass finals, but only for the
purpose of adding additional type constraints, not adding fields or
functionality, that might let you do something like this:

I disagree. You can already use composition for this kind of typing, and
adding rather arbitrary new constraints to the language does not add
anything useful IMHO. It merely serves to make the entire structure of the
language less logical and consistent.
 
R

Roedy Green

Its own primary index or index type?

In abundance you would write something like this:

<<<FOR anycollection height width * . FOR>>>

where height and width are fields of the elements of the collection.
In post fix that computes the area and displays it on the console.

collections are arrays, arrayLists, files etc.

The java equivalent is:

for ( Record r : collection )
{
int area = r.height * r.width;
System.out.printn( area );
}

before Java became more abundance-like you had to say:

for ( int i = 0; i<array.length; i++)
{

int area = r.height * r.width;
System.out.println( area );
}

Abundance is a DOS based Forth dialect. See
http://mindprod.com/jgloss/abundance.html if you are curious.

If I want to crank out a data entry app, it is far faster in Abundance
than Java and the end product is much faster for high speed data entry
and does far more automatic validation. However, DOS has great
limits, 640K, no gui, all character based.



--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
G

Gordon Beaton

Ada though requires you to write pages of code to define every new
unit of measure.

Not if you want plain integers, only if you want to restrict units in
the way you were asking earlier in the thread. How much code you
really need to write depends on what you want to be able to do with
your units. Think of them as classes.

Or were you really asking for a compiler that knows and does what you
mean, without you having to specify anything?

/gordon
 
A

Andrew Thompson

On 15 Jul 2005 11:00:31 +0200, Gordon Beaton wrote:
[snip]
Or were you really asking for a compiler that knows and does what you
mean, without you having to specify anything?

I was after a DWIMNWIS[1] compiler, but that would be better.
...Does anybody got some codes for one? ;)

[1] Do what I mean, not what I say.
 
R

Roedy Green

Or were you really asking for a compiler that knows and does what you
mean, without you having to specify anything?


Something in between. In normal English you can create a new unit of
measure just by saying it is a unit of measure the quatloo, or you can
define it in terms of some existing measure, e.g.

foot is 12 inches.

The equivalent declaration in a computer language should be equally
terse.

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
H

Hemal Pandya

Roedy said:
Just like the (cast) breaks the other type system.

The ability to break rules is important. But its better if it is
explicit. So I find dynamic_case<type> much better then (type).
Unfortunately Java did away with that. Maybe not so unfortunate, with
untyped collections the code would have been so full of them.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top