light weight types

J

John B. Matthews

Jeff Higgins said:
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.

Ah, I think I see what you mean. I recall stumbling over the namespace
change initially, but I can empathize with the authors' pride of
workmanship. In a different example, the class javax.swing.SwingWorker
was introduced in Java 1.6, but identical functionality is available in
Java 1.5 as org.jdesktop.swingworker.SwingWorker.
 
J

Joshua Cranmer

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.

I suppose I could have written that better. A better sentence:
The primary purpose of a recursive type is to allow the creation of
generic interfaces whose methods require the use of the implementing
class as parameters. Comparable objects compare only to other objects of
the same class, but the Comparable interface allows you to reason about
objects that have a defined total ordering.
 
K

Kevin McMurtrie

Roedy Green said:
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 complex number crunching, all of that masking and casting makes the
code a complete mess - a total loss for maintainability. That mess also
runs half as fast on x86 and x86-64.
 
J

Jeff Higgins

John said:
Ah, I think I see what you mean. I recall stumbling over the namespace
change initially, but I can empathize with the authors' pride of
workmanship.

I think the author has every reason to be proud.
The API is well thought out; simple and powerful.
(see: <http://tinyurl.com/JSR-275-API-Specification> (pdf))
As are the org.jscience.mathematics.* and physics.* APIs.

I'm a fan of the 'Benevolent Dictator' or 'Big Daddy'
fashion for library development: BD has a vision, works
hard to develop and advocate his vision, gains a wide base
of happy users and a cadre of dedicated maintainers, finally
retires after having spent some time basking in the limelight.

The JSR process seems to me a retreat to the Cathedral.
Not that the Bazaar is such a desirable place.
Perhaps somewhere just Uptown.
In a different example, the class javax.swing.SwingWorker
was introduced in Java 1.6, but identical functionality is available in
Java 1.5 as org.jdesktop.swingworker.SwingWorker.

I'm not sure I understand the whole javax namespace thing;
Why not a JCR (Java Community Repository) rather than a JCP?

You'll notice all of the 'I's above indicate an opinion if not a rant :)

JH
 
L

Lew

Kenneth said:
On Sat, 03 Oct 2009 17:12:18 -0700, Roedy Green wrote:

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

I find them more useful than you seem to, but your right about the
syntax. It is quite, quite ugly.

If by "ugly" you mean "elegant, useful and expressive", then I agree.
 
J

Joshua Cranmer

On Sat, 03 Oct 2009 17:12:18 -0700, Roedy Green wrote:

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

I find them more useful than you seem to, but your right about the
syntax. It is quite, quite ugly.

What syntax would you use then?
If you go for something that distinguishes between left and right
delimiters, you have just four choices: (), [], {}, and <> [1]. {}
denotes a block, so it is entirely the wrong thing to use IMHO. ()
denotes either overriding precedence, a type conversion, or a method
call, and I think it is already more than overloaded.

If you perhaps want only one token to separate the generics parameter
from the rest, you have many more choices. `:', `;', `,', and `.' are
untenable for what I hope are obvious reasons. `%', `^', `&', `*', `|',
`/', `+', `-', and `=' are all binary operator tokens, which means using
them as a delimiter in identifiers is again problematic (think name
lookup). `~', `!', `?' are unary (or ternary, in the last case)
operators, which eases on the problems of using them as a delimiter
token (id <TOK> id is unambiguously the generics invocation), but
reusing them would be awkward. That leaves us with `@', `#', and ``' and
`\' as possible tokens for unary style (`$' and `_' are both valid in
identifier names).

We can therefore reduce the syntax into one of six possible styles:
List[Integer]
List<Integer>
List@Integer
List#Integer
List`Integer
List\Integer

The last one has a `\u' problem (it's translated before tokens are
read), so that is pretty much out of the question. Using ``' is
aesthetically horrendous, if you ask me. Annotations used `@' first;
besides, Integer@List looks more meaningful anyways (nothing stops one
from using it in that format anyways).

What List[Integer] has going for it is that the array syntax fits closer
into a notation of what a generics type generally does: it's a container
of some object. On the other hand, it looks like an array access, which
means that the parser would look rather interesting.

On the other hand, List#Integer is perhaps the second most appealing of
possible unary-style formats (following List$Integer, but that's a valid
identifier already!). The pound sign is unused as a token in Java, which
means the syntax is wholly unambiguous. Unary tokens have the notable
drawback that nested and/or multiple types are hard to write (should
A#B#C be A<B, C> or A<B<C>>? or do you do A#B, C?). You can get around
this by requiring the end token (e.g., List#Integer#), but then the
appeal of the single unary token rapidly vanishes.

In the end, the only one that ends up being rather possible is
List<Integer>. If you drop the objection to curly braces delimiting
blocks, List{Integer} also looks somewhat visually appealing, but I
think that so severely overloading the { is out of the question IMHO.

FWIW, if you think the generics syntax is bad, look at the BGGA closures
proposal. IMO, the single worst part about function pointers is that
there is no easy way to write them. Examples:

static { => int } answer = { => 42 };
{ int => String } toBinary = { int x => Integer.toBinaryString(x) };
{ String => int } parseInt = Integer#parseInt(String);
{ Box => int } getX = Box#getX();
{ String => Set<String> } singleton =
Collections#<String>singleton(String);
static for void eachEntry(int[] values, { int ==> void } block) {
for (int p : values) {
block.invoke(p);
}
} [2]

And, at one point (I think this part was backed out though), the
statement `return 42' meant something completely different from the
similar `return 42;'. Yowsers.


[1] In principle, you could also include \/ or perhaps /\ in this list,
but I'm just going to toss that possibility out from the get-go on the
basis that \u causes magic to happen before even the tokenization step,
so including that as part of an identifier is not recommended.

[2] I noticed as I was getting examples that some closures seemed to use
=> and others ==>. I think over the course of development, the closures
construct was changed to use ==> instead of =>, while the type
definition for function pointers remained =>.
 
T

Tom Anderson

On Sat, 03 Oct 2009 17:12:18 -0700, Roedy Green wrote:

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

I find them more useful than you seem to, but your right about the
syntax. It is quite, quite ugly.

What syntax would you use then?

public class TreeMap BINDING GENERIC-TYPE E WHERE E IMPLEMENTS
GENERIC-TYPE Comparable RECURSIVELY BINDING GENERIC-TYPE E implements
SortedMap RECEIVING BINDING GENERIC-TYPE E AS E
FWIW, if you think the generics syntax is bad, look at the BGGA closures
proposal. IMO, the single worst part about function pointers is that
there is no easy way to write them. Examples:

One of the main objections to closure proposals in any language (well,
java and python) is that the syntax is dreadful. But in all cases, this is
only because the proposers have for some reason chosen incredibly,
gratuitously, bad syntax. In python, in particular, there's a possible
closure syntax that is an incredibly natural extension of the current
function syntax. So where we write functions:

def foo(a, b): return a + b

We might write closures:

foo = def(a, b): return a + b

But somehow, all the proposals which got any traction were for things
like:

foo = LET CLOSURE-DEFINITION BINDING a, b RESOLVE DOWNWARDLY expr {{ a + b; return }}

Well alright, not quite, but really, they were bad.

The BGGA examples you quote are correspondingly horrible. What idiot is
responsible for this?

Can't we copy C's function pointer syntax, where function pointer types
look like cut-down function definitions?

void() a; // function taking no arguments and returning nothing
int() b; // could be a counter or something
double(double, double) c; // elementary arithmetic operations and the like
ResultSet(Date, Graphics) d; // i dread to think

Is there anywhere where this would be syntactically ambiguous? This is
fine:

public double(double) makeMultiplier(final double k) {
// ...
}

Because if you see a paren after what looks like return type but before a
method name, you know it's a function type.

The literal syntax, used to define closures, is harder. This is natural,
if a little verbose (note that this doesn't preclude the existence of
shorthands for small functions - maybe we could omit the 'return' and the
semicolon in such a case):

return double(double x) {return k * x;};

I can't think of a situation where it's genuinely ambiguous with any
existing syntax, but it might take a lot of lookahead to resolve - you
can't tell it's a function type rather than a function definition until
you hit the {. Plus, it looks a bit too much like an anonymous class
definition that happens to be missing the 'new'. It just feels a bit
shaky.

I'm tempted to steal that # you no longer need for generics syntax and do:

return #double(double x) {return k * x;};

But that's fugly. It would annoy Smalltalkers, though, so that's a plus.

Thinking of Smalltalkers, maybe we should put the parameter list (which is
also a type specification in java) inside the braces:

return {double(double x): return k * x;};

tom
 
J

Joshua Cranmer

public class TreeMap BINDING GENERIC-TYPE E WHERE E IMPLEMENTS
GENERIC-TYPE Comparable RECURSIVELY BINDING GENERIC-TYPE E implements
SortedMap RECEIVING BINDING GENERIC-TYPE E AS E

Introducing new keywords is an issue I didn't discuss, but suffice to
say that it's something that many of the people with a say in the future
of Java want to avoid.
We might write closures:

foo = def(a, b): return a + b

foo = lambda a, b: return a + b ?
foo = LET CLOSURE-DEFINITION BINDING a, b RESOLVE DOWNWARDLY expr {{ a +
b; return }}

The C++0x proposal amounts to something like the following:
auto foo = [](int a, int b) { return a + b; }

(I use the `auto' because I'm not even going to try figuring out what
type that construct is. Also, the first set of brackets is for the
variables the construct will capture.)

But as you point out, the ideal closure syntax in a language is closest
to the native definition of a function. In JavaScript and Python, all
functions are automatically closures [1]. Also, all closures seem to
automatically include all variables in enclosing instances in scope,
which I'm not sure is the best idea.

In any case, the use of { => } for function pointer syntax is completely
and utterly horrid; its use in closures is probably a continuation of
the same syntax for stylistic decisions.
The BGGA examples you quote are correspondingly horrible. What idiot is
responsible for this?

I always associate Neil Gafter with BGGA the most.
Can't we copy C's function pointer syntax, where function pointer types
look like cut-down function definitions?

Using a generics-like syntax might be the most tenable proposition, but
I'm not enthusiastic about what that would look like.
void() a; // function taking no arguments and returning nothing
int() b; // could be a counter or something
double(double, double) c; // elementary arithmetic operations and the like
ResultSet(Date, Graphics) d; // i dread to think

Is there anywhere where this would be syntactically ambiguous? This is
fine:

ResultSet(Date, Graphics) d; would require until the `d' to disambiguate
between an attempt at a function call and an attempt at a function
pointer definition. That might make the resulting language something
other than LL(1), but I'm not entirely sure. In any case, it would make
writing a parser for the language interesting :).
 
J

Joshua Cranmer

But as you point out, the ideal closure syntax in a language is closest
to the native definition of a function. In JavaScript and Python, all
functions are automatically closures [1]. Also, all closures seem to
automatically include all variables in enclosing instances in scope,
which I'm not sure is the best idea.

catch(DanglingFootnoteError e) {

[1] In my work with JavaScript, I've come to strongly dislike this
feature. Since a function is a closure, it keeps its context for all
enclosing scopes while the function (say, a listener function) is live.
All the local variables of the enclosing scopes are therefore still in
scope, and therefore still alive. Now, when you throw in a reference
counted system, that means that it is very easy to generate refcount
cycles simply because you added a listener.

}
 
J

Joshua Cranmer

That seems awfully like the FCM proposal, which doesn't seem to get a
lot of coverage in this group. Do folks dismiss it, or is it just
lesser known?

<http://docs.google.com/Doc?id=ddhp95vd_0f7mcns>

It's generally lesser known, as many of the closure adherents don't want
to make do with a Java "closures lite" solution (which is essentially
what FCM is: basically a way to define a function in the middle of a
method, as opposed to a true closure that handles control flow of the
enclosing [1] method). Conversely, the people who aren't thrilled about
closures generally opt for something like the CICE+ARM proposal, which
is basically "shorten the syntax for simple anonymous inner classes and
throw in the one construct that closures people are really pining for."

In short, it's the middle ground between two rather polarized sides in
the debate. Which means that most people who count find it untenable,
since there is too much of the other side in it. The proposal, as nice
as it is, seems to be rather defunct nowadays.

I've become rather convinced that the question of closures in Java will
end up being "none." However, I am still undecided as to whether to
cheer or bemoan that fact.

[1] Is it the enclosing method or the invoking method? The syntactic
issues so overwhelms me that I've never actually bothered to try to
figure out which.
 
T

Tom Anderson

That seems awfully like the FCM proposal, which doesn't seem to get a
lot of coverage in this group. Do folks dismiss it, or is it just
lesser known?

<http://docs.google.com/Doc?id=ddhp95vd_0f7mcns>

It's generally lesser known, as many of the closure adherents don't want to
make do with a Java "closures lite" solution (which is essentially what FCM
is: basically a way to define a function in the middle of a method, as
opposed to a true closure that handles control flow of the enclosing [1]
method).

Since when was that the "true" meaning of 'closure'? That's a genuine
question - i hadn't come across the idea of nonlocal control flow being
essential to closures before. Indeed, it seems to me like an incredibly
bad idea which definitely should not be in the language.
In short, it's the middle ground between two rather polarized sides in
the debate. Which means that most people who count find it untenable,
since there is too much of the other side in it. The proposal, as nice
as it is, seems to be rather defunct nowadays.

Shame. It mostly looks pretty good, although the stuff about automatic
conversion to single-method interface types is decidedly iffy.
I've become rather convinced that the question of closures in Java will
end up being "none." However, I am still undecided as to whether to
cheer or bemoan that fact.

Better nothing than BGGA!
[1] Is it the enclosing method or the invoking method? The syntactic
issues so overwhelms me that I've never actually bothered to try to
figure out which.

Lexically enclosing.

I think.

And i really don't understand how that would work:

CLOSURE-TYPE makeClosure() {
CLOSURE-TYPE myClosure = {
return null;
};
return myClosure;
}

void callClosure() {
CLOSURE-TYPE someClosure = makeClosure();
someClosure.invoke(); // A
}

void main() {
callClosure();
}

Where does execution go after the line marked A? Oh, apparently we get a
UnmatchedTransfer exception? Christ on a bike. Have the people who come up
with this shit ever actually programmed a computer?

tom
 
T

Tom Anderson

Introducing new keywords is an issue I didn't discuss, but suffice to say
that it's something that many of the people with a say in the future of Java
want to avoid.

I would like to clarify that my suggestion was not entirely serious. I was
merely demonstrating that a skilled programmer can write COBOL in any
language. Although making it compile is another matter.
foo = lambda a, b: return a + b ?

Well:

foo = lambda a, b: a + b

is already legal! I can't remember why everyone thinks we can't extend the
lambda syntax to handle multiple statements. There must be a good reason,
though, right? Right?
foo = LET CLOSURE-DEFINITION BINDING a, b RESOLVE DOWNWARDLY expr {{ a +
b; return }}

The C++0x proposal amounts to something like the following:
auto foo = [](int a, int b) { return a + b; }

(I use the `auto' because I'm not even going to try figuring out what type
that construct is. Also, the first set of brackets is for the variables the
construct will capture.)

The square brackets are somewhat horrible. Interesting idea to make
capture explicit, though - i don't recall any of the python proposals
proposing that, probably because lambda doesn't at the moment.
But as you point out, the ideal closure syntax in a language is closest to
the native definition of a function. In JavaScript and Python, all functions
are automatically closures [1]. Also, all closures seem to automatically
include all variables in enclosing instances in scope, which I'm not sure is
the best idea.

In any case, the use of { => } for function pointer syntax is completely and
utterly horrid; its use in closures is probably a continuation of the same
syntax for stylistic decisions.
The BGGA examples you quote are correspondingly horrible. What idiot is
responsible for this?

I always associate Neil Gafter with BGGA the most.

Oh yeah, and Gilad Bracha. Both complete troublemakers. I love the idea
that a guy who works on C# and believes java is dying is an influential
force, rather than being burned in effigy.
Using a generics-like syntax might be the most tenable proposition, but I'm
not enthusiastic about what that would look like.

I don't see why that would be a good idea. Closures and generics are
completely orthogonal, aren't they? So why reuse the syntax? And how would
you write generic closures? For example, Collection<E> needs to able to
take a function mapping E to boolean as a parameter to the removeAll and
retainAll overloads it will surely grow.
ResultSet(Date, Graphics) d; would require until the `d' to disambiguate
between an attempt at a function call and an attempt at a function
pointer definition. That might make the resulting language something
other than LL(1), but I'm not entirely sure. In any case, it would make
writing a parser for the language interesting :).

I would not only make it not LL(1), it would make it not LL(k) for any k.
It would be LL(n), if that even means anything.

Okay, bring on the hashes!

tom
 
J

Joshua Cranmer

It's generally lesser known, as many of the closure adherents don't
want to make do with a Java "closures lite" solution (which is
essentially what FCM is: basically a way to define a function in the
middle of a method, as opposed to a true closure that handles control
flow of the enclosing [1] method).

Since when was that the "true" meaning of 'closure'? That's a genuine
question - i hadn't come across the idea of nonlocal control flow being
essential to closures before. Indeed, it seems to me like an incredibly
bad idea which definitely should not be in the language.

I suppose that FCM does provide full closures, strictly according to the
definition of closure. But then again, Java already has a limited form
of closures: inner classes, defined within methods, gain access to the
(final) local variables in scope.

This is roughly the story as I understand it:
It all begins, I think, with the try-finally construct. Whenever you
work with native resources, you typically need to open them and then
always close them, such that this becomes boilerplate:
SomeObject foo = /* get from somewhere */;
foo.open();
try {
// Magic foo operations
} finally {
foo.close();
}

The typical name for this is Automatic Resource Management (the ARM in
CICE+ARM). The idea is to be able to simplify that into:
with (foo.open()) {
// Magic foo operations
}

People then got the idea that it would be nice to be able to create
arbitrary control structures--the only other one I've seen that looked
remotely useful (indeed, the /only/ other I've seen at all) was some
sort of forEachInMap construct. This can of course be implemented with a
sufficiently-advanced closures framework, specifically one allowing
non-local control flow modification.

Now there's something else that a lot of BGGA proponents seem to cite.
Something called "Tennent's Correspondence Principle" which I've
actually found very hard to track down. Apparently, it roughly states
that |expression| should be equivalent to |{ ==> expression }.invoke()|
(to use the BGGA syntax). The BGGA proponents cite that as the reasoning
behind having the non-local control flow, but it seems to be an open
question as to whether or not the guy actually meant to include the
effects of control flow statements in his principle.
Shame. It mostly looks pretty good, although the stuff about automatic
conversion to single-method interface types is decidedly iffy.

It is ugly, but closures proponents would tell you that it's necessary
to tack closures onto the current language: it represents the ability to
use closures with classes not designed with them in mind.
Better nothing than BGGA!

Well, I gave up on BGGA after seeing a conversation to this effect:
"Well, of course { => return 42 } is the correct answer; why would
anyone think it should be { => return 42; }?" Even if that part is
completely eradicated from the final proposal, just the mere fact that
proponents didn't realize the pitfall in having the presence or lack of
the statement delimiter do two *completely* different things is enough
in my mind to banish it to the deepest flames of Hell for all eternity.
Where does execution go after the line marked A? Oh, apparently we get a
UnmatchedTransfer exception? Christ on a bike. Have the people who come
up with this shit ever actually programmed a computer?

Well, Neil Gafter works for Microsoft now, so I'm going to guess the
answer is `no.' :)
 
L

Lew

Tom said:
Well:

foo = lambda a, b: a + b
is already legal!

Not in Java it isn't.
I can't remember why everyone thinks we can't extend
the lambda syntax to handle multiple statements. There must be a good
reason, though, right? Right?

Maybe once Java has such a lambda syntax we could.
 
A

Arne Vajhøj

Kenneth said:
I find them more useful than you seem to, but your right about the
syntax. It is quite, quite ugly.

Java use the same syntax for generics as other languages which
Java in general share syntax with does.

It would have been extremely confusing not to have used the
syntax chosen.

Arne
 
R

RedGrittyBrick

Joshua said:
On Sat, 03 Oct 2009 17:12:18 -0700, Roedy Green wrote:

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

The others are usually always bad but I like Perlish. Just not in my Java.
[Snip]

I find them more useful than you seem to, but your right about the
syntax. It is quite, quite ugly.

What syntax would you use then?
We can therefore reduce the syntax into one of six possible styles:
List[Integer]
List<Integer>
List@Integer
List#Integer
List`Integer
List\Integer

List of Integer
 
L

Lew

List of Integer

It was hard enough achieving compatibility with the introduction of 'enum' as
a keyword. We don't want to be introducing COBOLish syntax through new
keywords if we can avoid it.
 
R

RedGrittyBrick

Lew said:
It was hard enough achieving compatibility with the introduction of
'enum' as a keyword. We don't want to be introducing COBOLish syntax
through new keywords if we can avoid it.

Thats it! I'm taking you off my mailing list of JOBOL announcements. So
there!

Hmm,
private Map of something that extends Integer and a List of something;
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top