light weight types

A

Alessio Stalla

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.

From my experience in another language (Common Lisp) that has had
closures from its inception, I think the association between closures
and ARMs (and control flow in general) is not what closures are all
about. Closures are simply functions that "close over" (capture) the
lexical environment they are defined in. In all effects closures in
Java should be like anonymous inner classes with a single method,
except that they should be able to modify the bindings they capture
(i.e., capture non-final variables as well). In fact, closures can be
used to implement simple message-passing OO systems with little
effort, so the analogy with classes holds.

In general, closures can be used for many things: callbacks, higher-
order functions (think Comparator), and, yes, ARMs. Apart from the
ugly syntax, introducing twists and complications in a simple concept
like closures just to make ARMs a little simpler to write is the main
mistake by the proponents of BGGA. For the record, I like the syntax
inspired by C function pointers.
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.

I don't know where they took that principle from, and it seems silly
to apply it to everything. Definitely closures do *not* respect it in
other languages I know; e.g. a return inside a closure returns from
it, not from the enclosing function/method, and for a reason: doing
otherwise would severely limit the usefulness of passing around
closures and call them at a later time, when the defining method is no
longer being executed - which is the main reason for having closures!
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.



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.

I completely agree!

-- Alessio
 
R

Roedy Green

How was that?

Impressive! I am going to use it in the entry to help explain
generics.

You did one of the things I like to see in docs, start with the simple
case and gradually add the complexities.
--
Roedy Green Canadian Mind Products
http://mindprod.com

Smart data structures and dumb code works a lot better than the other way around.
~ Eric S. Raymond The Cathedral and the Bazaar
 
R

Roedy Green

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>.

did you mean to say there:

You can store any A into a Container<A>, so if B is a subclass of A,
besides an A you can also put a B into Container<A>.

What did you mean by "a container stores its type?" just that you can
put an A into a Container<A>?


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

Smart data structures and dumb code works a lot better than the other way around.
~ Eric S. Raymond The Cathedral and the Bazaar
 
R

Roedy Green

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.

I don't understand. I looked at the definitions of Comparable and
Comparator, compare, compare to, and their implementations. I saw no
use of recursive types.
--
Roedy Green Canadian Mind Products
http://mindprod.com

Smart data structures and dumb code works a lot better than the other way around.
~ Eric S. Raymond The Cathedral and the Bazaar
 
T

Tom Anderson

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.

That's a good summary of, or prologue to, the FCM story, i think - java
already has the semantics, let's add the syntax. And add some weird bonus
syntax which directly relates inner classes and closures, to drive the
point home.
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
}

Okay, yes. That angle of approach explains a lot.

What other camps are there? There are the
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.

Yes, Gafter mentions this - it's defined in a book which is now out of
print. Some might say this was convenient (shades of Joseph Smith's golden
plates). Others might say, "Hey, perhaps there's a REASON that book is out
of print, DICKNIPPLES.".
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.

I do wonder about that. And also why this principle is more important than
any other holy commandment. Gafter mentions somewhere that it's good
because in their experience, things which violate the principle also lead
to bad consequences in real life, so it's a useful tool. The problem is
that there are quite clearly some things which don't violate the principle
which lead to bad consequences in real life. Like, for instance, the BGGA
proposal.
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.

You could have a battery of import-staticable adaptor methods. But yes, it
helps, and it's not *that* ugly.
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.


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

Burn 'em! Burn the lot of 'em!

tom
 
L

Lew

True. But since that part of the post was a digression about python,
irrelevant.

That was completely unclear from the context, which was Joshua
Cranmer's suggestion about a possible Java syntax.

I saw nothing in either Joshua's post or yours that made it clear to
me that it was about Python, even now after reviewing the relevant
posts and seeing the word "Java" in that part of the discussion. But
I'll take your word for it, it was a digression about Python.
 
T

Tom Anderson

Okay, yes. That angle of approach explains a lot.

What other camps are there? There are the

By which i mean, of course, there are the ARMourers you mention, the
Swingers, who are tired of writing three or more lines of boilerplate in
their handler implementations, and the Functionalists, who want to make
their code more incomprehensible^W elegant with the aid of map, filter and
reduce. Who else?

tom
 
R

Roedy Green

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<?>.

This does not seem right. What did you mean?

I think you might have meant this:

Since Container<?> stores objects of any type, in particular it stores
objects of type 'A'. Thus Container<A> is a subtype of (and thus
convertible to) Container<?>.

I have formatted, slightly edited and posted your explanation at
http://mindprod.com/jgloss/generics.html#BOUNDS
--
Roedy Green Canadian Mind Products
http://mindprod.com

Smart data structures and dumb code works a lot better than the other way around.
~ Eric S. Raymond The Cathedral and the Bazaar
 
T

Tom Anderson

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;

Under ECMA standard COBOJ, that should actually be:

private Map of something that extends Integer and a List of something else;

tom
 
J

Joshua Cranmer

I don't understand. I looked at the definitions of Comparable and
Comparator, compare, compare to, and their implementations. I saw no
use of recursive types.

I keep forgetting that it's defined as Comparable<T>, not Comparable<T
extends Comparable<T>>. Enum is actually defined recursively; Comparable
is just typically used in such a manner. I had also planned to motivate
<? super T> (with the canonical example for such bounds, <T extends
Comparable<? super T>>) here, but changed my mind later.
 
T

Tom Anderson

That was completely unclear from the context, which was Joshua
Cranmer's suggestion about a possible Java syntax.

In this post:

http://groups.google.co.uk/group/comp.lang.java.programmer/msg/927e21d3c341dd09?hl=en

I wrote:

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

In his reply, Joshua trimmed from "In python" to just before "We might".
Anyone who was, for some inexplicable reason, not following our every word
with rapt and studious attention would have been thrown off the scent
there.
I saw nothing in either Joshua's post or yours that made it clear to me
that it was about Python, even now after reviewing the relevant posts
and seeing the word "Java" in that part of the discussion. But I'll
take your word for it, it was a digression about Python.

For my next trick, i will conceal an exegesis about FORTRAN somewhere in
the next month's posts.

tom
 
A

Arne Vajhøj

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.

New syntax is new syntax that makes the syntax more complex.

I do not think adding new keywords is less complex than reusing
existing keywords for a different purpose.

"of" obviously does not fit well with Java, because it is not
a C/C++/Java/JavaScript/C# syntax family keyword.

Arne
 
A

Arne Vajhøj

Tom said:
Under ECMA standard COBOJ, that should actually be:

private Map of something that extends Integer and a List of something else;

List(Of Something)
Dictionary(Of Something1, Something2)

are both valid types in VB.NET ....

Arne
 
A

Arne Vajhøj

Lew said:
Thank goodness that we don't need to use any new syntax to express
parametric types, then.

<T> is new syntax. Just not new keywords. And it definitely added
complexity - just consider how many questions are asked about it here.

It also added benefits though. It is definitely possible to argue
that the benefits justify the added complexity.

Arne
 
L

Lew

Arne said:
<T> is new syntax. Just not new keywords. And it definitely added
complexity - just consider how many questions are asked about it here.

It is most assuredly not new syntax. The Java version that introduced it hits
end-of-service-life in less than four weeks. It was introduced over five
years ago. In what IT context is five years considered "new"?
 
A

Arne Vajhøj

Lew said:
It is most assuredly not new syntax. The Java version that introduced
it hits end-of-service-life in less than four weeks. It was introduced
over five years ago. In what IT context is five years considered "new"?

It was new syntax when it was added.

Arne
 
A

Arne Vajhøj

Jeff 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.

In many contexts including deployment and legal it has advantages
if some functionality is part of Java instead of an external package.

Whether this particular package has sufficient wide usage to warrant
being included I do not know.

Arne
 

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,744
Messages
2,569,483
Members
44,901
Latest member
Noble71S45

Latest Threads

Top