Closures and Stuff

2 views
Skip to first unread message

ebresie

unread,
Mar 7, 2008, 11:02:31 AM3/7/08
to The Java Posse
Hey guys...Hope I'm not going to start something too big here...

I'm still new and confused about Closures as a whole...I've tried to
read as much as I can but still am confused. I understand many of
the

My understanding of closures put simple, a closure is a way of having
a block of code that can be used (assigned to a "method reference";
passed to other caller methods which would call it). So in a respect,
it's like an annoymous method but with a "handle" of some type that
allows it to be passed around or to method passing using the (void *)
type thinking from C/C++.

It also provides the ability to group a block of code in a basic
atomic level so that it could be passed of in a multiple processor/
core environment more efficiently.

Is that correct?

While reviewing some basic java tutorial material, I saw mention of
some static initalizers where we have something like

static {
// initalization code
// basic code that is gets executed by all
}

Would utilization of some of this be of use in the closure? Maybe
with some form of aliasing?

I am almost afraid to suggest it, but taking from C/C++, would adding
an equivalent

#define closureName static {}

be of any use?

I guess I'm hoping to keep it simple..

---

I would love to hear about any of the discussions that may have
occured at the roundout.


Eric

Reinier Zwitserloot

unread,
Mar 8, 2008, 6:20:16 PM3/8/08
to The Java Posse
Your analysis right up until you mention 'static initializes' is right
on. Then, from that point onward, I have absolutely no idea why you
even think these are related.

static{} code is the opposite of a closure. A closure is extremely
'flexible' - it is as you say a way to define a bunch of code but then
say: Don't run this, I'm just writing it here so I can do something
else with it. The 'else' varies. static {} on the other hand is the
opposite of that. It always runs, exactly once, you can't stop it, and
you have little control over when it runs exactly. You can't 'point'
to it, you can't even call it.

You can use closures for the following things:

1. Pass it to a modifier function that decorates it. The modifier
function can also choose to not run the code at all, or run it
multiple times. Example:

foreach syntax is perfectly doable as a library if you had closures
support. You'd have a foreach function that took two parameters: A
collection of Ts, and a closure that took as input a T and outputs
nothing.

resource guarding: For example, new File("/whatever/
whatever.txt").readWith(closure(InputStream in) { /* code that fiddles
with the inputstream */});. The 'readWith' method will first open a
new inputstream, then give it to the closure and run the closure, all
the while guarding it with a try/finally to close the inputstream no
matter what the closure does, be it return normally, or throw an
exception.

instrumenting: You could write a method that takes a closure, reports
that the closure is now being run, and report when it is done.

filter, map, and other standard functional programming language
features: 'filter' is the ability to pass a {T => boolean} closure to
a list, so that the list can run the closure for each item in it, and
build a new list, containing only those elements for which the closure
returns true. You could for example take a list of strings, and
eliminate all strings inside it with spaces in it, leaving just the
single-word strings in it. map takes a T and returns a V, which allows
you to take a list, and build from it a new list, by running the
closure on each item in the list. You could for example take a list of
strings, and turn it into a list of integers (the lengths of each
string), doing something like:

List<String> list = Arrays.asList("hello", "world!", "how", "are",
"you?");
List<Integer> lengths = list.map(int closure(String in) { return
in.length(); });

and now lengths would be a list with [5, 6, 3, 3, 4] in it.

In general, anytime you have two methods that are almost identical but
it is difficult to eliminate the repetition in them, you can usually
fix it with closures.

For example, two days ago I had some code which would take a list and
an index and find the closest index with a non-null item in it. (e.g
given a list with ["Hello", null, null, "World", null, "Foobar"], and
the index '2', I want '3', because the item with index 3 is non-null
and closest to 2). A day later I needed to find the nearest item in
the list to a certain index with a known string in it. Instead of just
copying over a lot of the code in my original method, or adding a
boolean flag to pick which type of filter to use (non-null, or, exists
in this predefined list of accepted words), I created a custom little
interface with one method in it (public boolean qualifies(T t)), and I
created a little instance of this interface on the fly and passed it
to my findNearestQualifyingItemInList' method. You can do this in java
now but its kinda wordy.

2. You can also use closures for deferred execution.

So far all examples still meant the code would run immediately. In
other words, the 'context' of the code (E.g. the stack, for example)
wouldn't change that much. However, closures can also be used to store
code and run it in very different places. For example, a simple
'button click listener' - a block of code you can give to a button
widget which the button will call when it is clicked, can also be
written as a closure. In this case, however, the context is completely
changed. The method that defined the closure has long stopped
executing, and now we're someplace else entirely. This can be useful
for all sorts of stuff: event listeners of all kinds, passing things
into another thread's run queue (the way you need to pass things into
the swing event dispatcher thread if you want to change widgets
around), or even just saying: Take this code and run it exactly 5000
milliseconds from now. You can do all of this right now, closures
mostly make it a bit less wordy.

ebresie

unread,
Mar 10, 2008, 2:36:18 PM3/10/08
to The Java Posse
I appreciate your comments, they clear up a number of things for me...

As I don't have any direct guidances around, I depend on comments like
yours to keep me straight and not off base.

On Mar 8, 6:20 pm, Reinier Zwitserloot <reini...@gmail.com> wrote:
> Your analysis right up until you mention 'static initializes' is right
> on. Then, from that point onward, I have absolutely no idea why you
> even think these are related.

I was trying to relate existing java constructs into the current
context. I was
thinking that an extensions to this existing static {} capability
could avoid
adding new keywords and simplfy things a little bit. I guess it's not
that
simple.

> static{} code is the opposite of a closure. A closure is extremely
> 'flexible' - it is as you say a way to define a bunch of code but then
> say: Don't run this, I'm just writing it here so I can do something
> else with it.

So this goes back to one of my early comments, it is sort of like
a #define in C/C++. So would adding a #define type construct
to the java language be an alternative to closures?

Or maybe an @defineClosue() annotation of some type? Of course I'm
new to annotations as well so this one is also probably completely
off
base as well.

> The 'else' varies. static {} on the other hand is the
> opposite of that. It always runs, exactly once, you can't stop it, and
> you have little control over when it runs exactly. You can't 'point'
> to it, you can't even call it.
>
> You can use closures for the following things:
>
> 1. Pass it to a modifier function that decorates it. The modifier
> function can also choose to not run the code at all, or run it
> multiple times. Example:
>
> foreach syntax is perfectly doable as a library if you had closures
> support. You'd have a foreach function that took two parameters: A
> collection of Ts, and a closure that took as input a T and outputs
> nothing.
>
> resource guarding: For example, new File("/whatever/
> whatever.txt").readWith(closure(InputStream in) { /* code that fiddles
> with the inputstream */});. The 'readWith' method will first open a
> new inputstream, then give it to the closure and run the closure, all
> the while guarding it with a try/finally to close the inputstream no
> matter what the closure does, be it return normally, or throw an
> exception.

So this case is kind of like the "(new ActionHandlers(){/* some action
handler
block of code here*/ })" type usage only
with a "defined" or "closure" named block of code instead of an
anonoymous block of
code.

> instrumenting: You could write a method that takes a closure, reports
> that the closure is now being run, and report when it is done.
>
> filter, map, and other standard functional programming language
> features: 'filter' is the ability to pass a {T => boolean} closure to
> a list, so that the list can run the closure for each item in it, and
> build a new list, containing only those elements for which the closure
> returns true. You could for example take a list of strings, and
> eliminate all strings inside it with spaces in it, leaving just the
> single-word strings in it. map takes a T and returns a V, which allows
> you to take a list, and build from it a new list, by running the
> closure on each item in the list. You could for example take a list of
> strings, and turn it into a list of integers (the lengths of each
> string), doing something like:
>
> List<String> list = Arrays.asList("hello", "world!", "how", "are",
> "you?");
> List<Integer> lengths = list.map(int closure(String in) { return
> in.length(); });
>
> and now lengths would be a list with [5, 6, 3, 3, 4] in it.

Maybe this is one of the points that confuses me..why have this and
not just define a static utility method?

Is keeping the code short the main reason here as opposed to having
a static utility method that takes the input string list and returns
an integer list?

Or is the intent to make it more like other functional languages?

> In general, anytime you have two methods that are almost identical but
> it is difficult to eliminate the repetition in them, you can usually
> fix it with closures.
>
> For example, two days ago I had some code which would take a list and
> an index and find the closest index with a non-null item in it. (e.g
> given a list with ["Hello", null, null, "World", null, "Foobar"], and
> the index '2', I want '3', because the item with index 3 is non-null
> and closest to 2). A day later I needed to find the nearest item in
> the list to a certain index with a known string in it. Instead of just
> copying over a lot of the code in my original method, or adding a
> boolean flag to pick which type of filter to use (non-null, or, exists
> in this predefined list of accepted words), I created a custom little
> interface with one method in it (public boolean qualifies(T t)), and I
> created a little instance of this interface on the fly and passed it
> to my findNearestQualifyingItemInList' method. You can do this in java
> now but its kinda wordy.

This may answer my previous question...so the justification is to help
shorten code...right?
> > Eric- Hide quoted text -
>
> - Show quoted text -

Alexey Zinger

unread,
Mar 10, 2008, 6:01:46 PM3/10/08
to java...@googlegroups.com
I'm no expert on the closures debate or language theory in general, but I'll
add my two cents here, if you don't mind.

As you rightfully pointed out, a closure is more or less a referenceable and
callable code block. At the moment, the closest relative that exists in Java
is the anonymous inner class:

Collections.sort(myList, new Comparator<String>() {
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}});

At first glance, it doesn't seem that different than one of the closure
approaches (forgive me if I'm mangling syntax):

Collections.sort(myList, {String s1, String s2 => return s1.length() -
s2.length; });

And indeed, one of the suggested implementations would simply consist of syntax
sugar that recognizes use of single-method interfaces and convert the latter
into the former at compile time. I know how to type pretty well and I don't
really mind a few extra keystrokes.

The real difference comes about when one wants to do flow control: returns,
breaks, exception handling. Syntax sugar solution that doesn't extend go
beyond what we can do now with anonymous inner classes doesn't solve these
problems. The infamous for-as-a-library example:

// this could be simulated with anon inner classes
myList.for({item => System.out.println(item);});

// but there's no way to do this except with... exceptions (ugly IMO)
blah = ...;
myList.for({item => if(item.equals(blah)) return true; });

There's similar issues with variable scope. Currently, anonymous inner classes
can see variables declared in enclosing scope, but only if they're declared
final. It's still possible to make them variable, but it quickly gets ugly:

final int[] counter = new int[1];
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
++counter[0];
}});

I'm actually willing to live with it (have been for 10 years now), but many
others are antsy to clean up a bit. I'm sure professors don't feel great
teaching those kinds of things to their students either.

I _think_ that's basically all that closures buy us: occasional syntax
clean-up, flow control and special variable scope. You can see though that the
last 2/3 of that are hard work to get right on top of existing JVM technology
and language.

--- ebresie <ebr...@gmail.com> wrote:


Alexey
2001 Honda CBR600F4i (CCS)
1992 Kawasaki EX500
http://azinger.blogspot.com
http://bsheet.sourceforge.net
http://wcollage.sourceforge.net

____________________________________________________________________________________
Never miss a thing. Make Yahoo your home page.
http://www.yahoo.com/r/hs

ebresie

unread,
Mar 11, 2008, 10:10:39 AM3/11/08
to The Java Posse
Just curious about the rational for not just having a "closure
utilities" class with the necessary "closure methods" , and then pass
the object and/or make a call against a instance of the "closure
utilites" objects."closure method()"? Is this seen as more
complicated than a closure construct addition?

Kevin Wong

unread,
Mar 11, 2008, 11:18:10 AM3/11/08
to The Java Posse
One place in which I am often in need of closures is unit tests, where
test methods are often identical except for isolated variances. I've
used a Closure interface in the past as a workaround, but it's clunky.

Reinier Zwitserloot

unread,
Mar 11, 2008, 12:47:12 PM3/11/08
to The Java Posse


On Mar 10, 7:36 pm, ebresie <ebre...@gmail.com> wrote:
> So this goes back to one of my early comments, it is sort of like
> a #define in C/C++.  So would adding a #define type construct
> to the java language be an alternative to closures?

#define is something completely different and what it does is
completely foreign to java compilers. #define actually sucks A LOT,
because the C preprocessor is turing complete and dependent on
unknowns (such as 'which OS are we compiling on?'. It is therefore
impossible for a smart editor to actually know what is going on, and
therefore all attempts to write refactor scripts, implementing
features such as 'come from', 'find implementors', 'go to definition'
and other such niceties are at best guesstimates instead of the rock-
solid results you get with java (unless you use string literals in
reflection. You should definitely not do that, ever).

If you mean you can use #define to link an arbitrary set of code to a
name so you can later just use the name, technically, yes, but, the
way #define works compared with the way closures work is -completely-
different. #define is a simple search/replace run across the source
files. You can not use this to implement almost every example I gave.
Go try it. You won't get far.

>
> Or maybe an @defineClosue() annotation of some type?   Of course I'm
> new to annotations as well so this one is also probably completely
> off
> base as well.

You are. Read up on annotations first.

>
> So this case is kind of like the "(new ActionHandlers(){/* some action
> handler
> block of code here*/ })" type usage only
> with a "defined" or "closure" named block of code instead of an
> anonoymous block of
> code.

Yes. One of the closure proposals (CICE - google "CICE crazy bob" for
more info) recognizes the similarity and simply proposes some syntax
sugar to reduce the cruft you need to write. However, the above code
(called 'anonymous inner classes' to be pedantic about it) cannot do
some things that closures can:

1. 'return', 'break' and 'continue' are not transparent. any of those
statements inside the anonymous inner class definition do not return,
break, or continue anything outside of it. This would mean that an
Anonymous Inner Class based foreach version can't be used to write
something like:

public String findAStringWithASubStringInitt(List<String> list, final
String toFind) {
Utilities.ForEach(list, new ForEachProcessor<String>() { public void
process(String item) {
if ( item.contains(toFind) ) return item;
}});
}

the 'return' statement tries to return from the process method, but
the process method has a void type. Trying to solve this with more
generics gets rather ugly. The BGGA proposal (BGGA closure should be a
good google search term) does address this problem (but the CICE
proposal does not). Unfortunately to make it work in java, the
solution is a lot of complicated syntax sugar for using exceptions to
first get back to the containing method in the stack. Also, trying to
'return', 'continue', or 'break' relative to the containing method
makes absolutely no sense when the closure is used for deferred
execution. The BGGA solution is to throw a particular RuntimeException
if you try it, but this is an inferior solution, because in theory the
compiler could catch you anytime you screw up like that. There's a
half-arsed proposal to try and make this a compile-time catchable
problem but it's the one thing almost all BGGA detractors really
dislike.

Also, closures actually get their name from the notion that they
'close over' lexical scope. In other words, variables created in the
outer method are accessible to the closure. Note how in the above
snippet the closure is accessing the 'toFind' variable. toFind is not
part of the 'process' method at all, it's part of
findAStringWithASubstringInIt. You can still do this. However, java
restricts you to ONLY using 'final' variables in this way. The reasons
are complex, and it helps if you know how C works. Basically, local
variables (and parameters are also local variables) do not get
declared on the 'heap', but on the stack. Stacks are great - they
perform much better because they tend to remain entirely in the CPU's
cache (which is orders of magnitude faster than normal memory), and
you don't need to garbage collect anything. When the method returns,
boom, the stack cleanup automatically destroys all local variables.
However, therein lies the problem - closures can 'escape' their
context, when you use them for deferred execution (that deferred
execution thing really gums up the works, doesn't it?). Now the
closure still exists even when the method has returned, and thus all
local variables accessed by the closure either need to be declared on
the heap (which is more expensive), or copies need to be made (which
is cheap, but a copy means that trying to modify it doesn't modify the
original). Java decided not to silently use the heap for stuff
accessed in anonymous inner classes, and thus requires you to use
'final' so that a copy is just as good as the original. A simple way
around this is to use an array of size 1; array contents are always
defined on the heap.

ALL closure proposals include relaxing this restriction. CICE simply
lets you skip the 'final' if you never change the variable anyway, and
if you do, allows a keyword ('public') to indicate you want the
variable to be declared on the heap instead. BGGA and FCM go a step
further and silently relegate the variable to the heap (IIRC).


>
> > List<String> list = Arrays.asList("hello", "world!", "how", "are",
> > "you?");
> > List<Integer> lengths = list.map(int closure(String in) { return
> > in.length(); });
>
> > and now lengths would be a list with [5, 6, 3, 3, 4] in it.
>
> Maybe this is one of the points that confuses me..why have this and
> not just define a static utility method?

Okay. Write the static utility method then. You'll find that you
cannot do this. The whole point of 'map' is that one of the parameters
to the 'map function' is itself a function. You can't pass functions
around in java. You can only pass instances of interfaces. In fact,
this is how Collections.sort() works right now. You can write your own
'sort comparator', but that is code, and thus you need to implement
the Comparator<T> interface and provide an instance of this interface.
In practice this means people generally write an anonymous inner class
declaration. Those are needlessly wordy and have those pesky
restrictions on being able to use only 'final' local variables. If you
want to write a static utility that actually does the whole 'turn a
list of strings into a list of lengths' thing, then you are guilty of
copying code. You should never copy code. Copied code can not be
maintained. (Fix a bug in one of the copies and now go hunt for every
copy of this code and fix it everywhere). Therefore, the part that
loops over the list should be turned into one block. For this
particular example, the lines of code that we are isolating seem
trivial (1 to 2 at best), but that's just an artefact of what map
does. My example for finding the nearest qualifying item in a list is
about 12 lines or so. I definitely don't want to copy those 12 lines
everytime I need to find the nearest qualifying item in the list, for
different 'qualifier' functions. Same deal with trying to sort stuff.
Quicksort is not the type of algorithm you want to copy and paste a
bunch of times.

>
> This may answer my previous question...so the justification is to help
> shorten code...right?

Not just shorten, that's a bonus. A major goal is to eliminate
repetition of code. You can do this now with anonymous inner classes,
but those are extremely unwieldy.


Note that the major difference between the various closure proposals
is just which parts of the unwieldy anonymous inner classes syntax are
made somewhat less unwieldly, and how this is done. Those are the only
differences.

All closure proposals make it easier to create instances of interfaces
with only one method in them (such as for example Comparator<T>). BGGA
makes it easier to communicate 'return', 'break', and 'continue' to
the outer scope with complex sugar that uses exceptions under the
hood, but there's nothing stopping you from doing that now. Then
again, this makes the BGGA proposal a lot more complicated.

Reinier Zwitserloot

unread,
Mar 11, 2008, 12:57:38 PM3/11/08
to The Java Posse
On Mar 10, 11:01 pm, Alexey Zinger <inline_f...@yahoo.com> wrote:
> And indeed, one of the suggested implementations would simply consist of syntax
> sugar that recognizes use of single-method interfaces and convert the latter
> into the former at compile time.  I know how to type pretty well and I don't
> really mind a few extra keystrokes.

How can you dismiss the cruft surrounding a non-CICE 'Single Abstract
Method Anonymous Inner Class definition' as simply being something
solved with a few more keystrokes and not worthy of whining, when in
the next paragraph you indicate that the ability to bypass the cruft
introduced by rolling your own 'use an exception to break out of this
closure and return/break/continue something in the outer scope' as
crucial? They are two different kinds of cruft elimination. the
exception sugar is more involved, but it also adds a major load of
complications, primarily when the closure escapes the lifepspan of the
enclosing method and the whole notion of escaping out no longer makes
any sense.

There's cruft which seems a bit superfluous but can still impart
information, and cruft which is just cruft. The following line:

List<String> list = new ArrayList<String>();

contains zero cruft. The type (List) is different from the
implementation type (ArrayList) and this conveys useful information
(the author simply needs a list and decided to pick ArrayList, but you
should be able to change that around to something else). The two
repeated versions of the generics parameter <String> are almost always
considered to be overkill and proposals exist to reduce this, but,
technically, this stuff still indicates something. You could also
write something like List<? super String> on the left for the code to
have a different meaning.

Compare this to a non-CICE 'single abstract method anonymous inner
class declaration'. Such things contain cruft which adds nothing, only
makes it considerably harder to read. It also actively adds confusion.
Due to the need to add the method declaration as well, generally the
actual code in an anonymous inner class is indented 2 levels deeper
than the containing code, but this is clearly wrong: semantically it
is only one indent. After all, we don't indent the content of foreach
loops twice, either. And yet the only way to indent the code correctly
is to write the name of the type (e.g. Comparator<T>) and the method
declaration (e.g. public int compare(T a, T b)) on the same line, and
then close the 'closure' with a double close brace. That's not just
really ugly, it is very very hard to read. We're well beyond saving a
few keystrokes here.



> There's similar issues with variable scope.  Currently, anonymous inner classes
> can see variables declared in enclosing scope, but only if they're declared
> final.  It's still possible to make them variable, but it quickly gets ugly:

Instead of an array you can also write a Pointer<T> class which is
slightly cleaner.
Fortunately all closure proposals (including CICE) address this issue.


>
> I'm actually willing to live with it (have been for 10 years now), but many
> others are antsy to clean up a bit.  I'm sure professors don't feel great
> teaching those kinds of things to their students either.

Any professor that uses java to teach basic programming should be
fired. I love java to bits, but as a teaching language it's a few
levels beyond horrible. I question the sanity and intelligence of any
professor that thinks java is a suitable language for teaching
programming. Assuming for a moment a competent teacher, closures
should already be familiar. Then, explaining that in java (without any
closure proposals, that is), you have to jump through a few hoops to
get the same result is simply a matter of showing it, explaining what
and why, and moving on to the next lesson.

>
> I _think_ that's basically all that closures buy us: occasional syntax
> clean-up, flow control and special variable scope.  You can see though that the
> last 2/3 of that are hard work to get right on top of existing JVM technology
> and language.

I wouldn't file closures away under 'syntax sugar'. Closures are also
a different way of thinking. Whether or not the java world adapts to
this different way of thinking is another question, of course.
Personally I prefer CICE because i think it allows for a nicer
'evolution path' - you can start by introducing just CICE, then in a
later version you can stick 'long' returns/breaks/continues into CICE
with an alternative syntax (using e.g. labels, just like you have to
with long breaks and continues now), and if people really want it, you
can introduce the much debated function types.

Reinier Zwitserloot

unread,
Mar 11, 2008, 1:05:06 PM3/11/08
to The Java Posse
Closures aren't libraries. You can't try and emulate closures with a
library. If you suggest that a bunch of functional types are added to
e.g. java.util.funtypes or something, and that people use these mostly
by writing instances of them using the anonymous inner class syntax, I
strongly object.

Only BGGA introduces functional types in the first place. The FCM
proposal does have them, but the prototype does not, and Stephen
Colebourne himself is on the fence if functional types are even a good
idea. They are certainly a part of the closure concept that can be
left out. Your suggestion (if I understand you correctly) is to
implement ONLY the functional type stuff. That's taking the most
disliked and contended feature alone and leaving out the stuff almost
all closure fans agree on: Easier syntax for writing portable code
blocks.

Simple example of why function types are a bad idea:

1. {int, int => int}. Is this a function for an integer calculator
(examples: plus, minus, multiply, divide, powerto), or is this a
function that can compare two integers and tell which one is above the
other? These two things both have the {int, int => int} functional
type but they are not related to each other at all.

2. Lets assume {int, int => int} is indeed a calculator function of
sorts. Is it commutative (is closure(a, b) always the same as
closure(b, a)?) - let's say for the function that needs this type, you
need to be. Where do you write the documentation explaining this? On
the method? What if there's a whole batch of methods that need
commutative functions with the {int, int => int} syntax. Copy and
paste the documentation? That sounds like a bad idea. A: public
interface CommutativeIntegerOperation(int, int => int) is much nicer.
It's the same thing except this time we've given it a name, and
because it now has a name, you can stuff it in a class file
(CommutativeIntegerOperation.java), and add javadoc to it. Your
editors can now find this class, pop up the javadoc when you try and
write an implementation of a CommutativeIntegerOperation, etcetera.

function types are a form of 'structural typing' - the structure of
the object defines its type, instead of the name. Aside from javabeans
(get* is a getter, set* is a setter) and a main class (if it has a
public static void main(String[] args), I can run it), java is
ENTIRELY nominally scoped. The fact that both the Gun class and the
Camera class happen to have a 'shoot' method does not mean they are
interchangible. Contrast this to a structurally typed language like
javascript or python. There there is no such thing as a 'Gun' type.
The only thing you have is 'some object that happends to have a
shoot() method defined on it'. You can combine nominal and structural
typing (plenty of languages do so), but it would make jave very
complicated.

Alexey Zinger

unread,
Mar 11, 2008, 2:01:40 PM3/11/08
to java...@googlegroups.com
--- Reinier Zwitserloot <rein...@gmail.com> wrote:

>
> On Mar 10, 11:01 pm, Alexey Zinger <inline_f...@yahoo.com> wrote:
> > And indeed, one of the suggested implementations would simply consist of
> syntax
> > sugar that recognizes use of single-method interfaces and convert the
> latter
> > into the former at compile time. I know how to type pretty well and I
> don't
> > really mind a few extra keystrokes.
>
> How can you dismiss the cruft surrounding a non-CICE 'Single Abstract
> Method Anonymous Inner Class definition' as simply being something
> solved with a few more keystrokes and not worthy of whining, when in
> the next paragraph you indicate that the ability to bypass the cruft
> introduced by rolling your own 'use an exception to break out of this
> closure and return/break/continue something in the outer scope' as
> crucial? They are two different kinds of cruft elimination. the

Let me clarify it a bit. The way I see it, using anonymous inner classes
implementing single-method interfaces to encapsulate a callable code block
comprises the 20% of closure features that make 80% of people happy. If we
made anonymous inner classes implementing one-method interfaces represented
with special cleaner syntax that still compiled to the exact same bytecode, I'm
ambivalent about it. When I look at code, I don't care what it "reads" like
(within reason), only what it runs like and what it feels like to code against.
From those standpoints, I don't think CICE does not change anything. It's
syntax sugar, which doesn't mean it's bad or shouldn't be implemented, but the
bytecode will be exactly the same.

> exception sugar is more involved, but it also adds a major load of
> complications, primarily when the closure escapes the lifepspan of the
> enclosing method and the whole notion of escaping out no longer makes
> any sense.

My beef with implementing the other 80% of closures, such as more advanced
control flow by use of exceptions is that I _believe_ that it would be an
incredible feat to attempt to make it work without leaking abstraction in some
corner cases. I think it would be asking for a whole other volume of Java
puzzlers. I could be wrong. It's just what my gut is telling me right now,
when I try to think through the potential implementation concerns.

<snip>

> > There's similar issues with variable scope. Currently, anonymous inner
> classes
> > can see variables declared in enclosing scope, but only if they're declared
> > final. It's still possible to make them variable, but it quickly gets
> ugly:
>
> Instead of an array you can also write a Pointer<T> class which is
> slightly cleaner.
> Fortunately all closure proposals (including CICE) address this issue.

Indeed.

> > I'm actually willing to live with it (have been for 10 years now), but many
> > others are antsy to clean up a bit. I'm sure professors don't feel great
> > teaching those kinds of things to their students either.
>
> Any professor that uses java to teach basic programming should be
> fired. I love java to bits, but as a teaching language it's a few
> levels beyond horrible. I question the sanity and intelligence of any
> professor that thinks java is a suitable language for teaching
> programming. Assuming for a moment a competent teacher, closures
> should already be familiar. Then, explaining that in java (without any
> closure proposals, that is), you have to jump through a few hoops to
> get the same result is simply a matter of showing it, explaining what
> and why, and moving on to the next lesson.

I think when ECMAScript 4 comes out, it'll be good. Like everyone else
probably, I think the way I was taught was perfect, which was starting with
register programming on calculators followed by a bunch of fundamentals in a
higher-level language (Pascal) with minimal computer access -- you were forced
to think through your code written out in a notebook so as to find as many
mistakes as possible before you typed it up at a terminal and attempted to
debug it for real. I was just listening to the SE Radio episode with Dick
Gabriel, in which he mentions his sabbatical as a poet and his realization that
art education is all about teaching the artistic process, not specific
techniques, and that the same should hold true for the scientific/engineering
process. Okay, that was a hell of a tangent.

> > I _think_ that's basically all that closures buy us: occasional syntax
> > clean-up, flow control and special variable scope. You can see though that
> the
> > last 2/3 of that are hard work to get right on top of existing JVM
> technology
> > and language.
>
> I wouldn't file closures away under 'syntax sugar'. Closures are also
> a different way of thinking. Whether or not the java world adapts to
> this different way of thinking is another question, of course.
> Personally I prefer CICE because i think it allows for a nicer
> 'evolution path' - you can start by introducing just CICE, then in a
> later version you can stick 'long' returns/breaks/continues into CICE
> with an alternative syntax (using e.g. labels, just like you have to
> with long breaks and continues now), and if people really want it, you
> can introduce the much debated function types.

I don't think of closures in general as syntax sugar, but I do think that CICE
is, and as I mentioned above, it's not meant as a strictly negative judgment of it.

Reinier Zwitserloot

unread,
Mar 14, 2008, 11:53:52 PM3/14/08
to The Java Posse
Many good points, Alexey. A few notes:

I don't think its fair to presume a feature to be a bad idea just
because it generates a whole new volume of java puzzlers. Generics are
clearly worth it. I'm aware that generics are somewhat controversial
and there are those who feel they were a bad idea, but I don't. I am
sympathetic to any attempt to improve them (e.g. reifing them), but
given the restrictions of backwards compatibility, generics as
implemented in 1.5 was the only way, and it has made java a better
language.

It has also created a large and extremely complicated batch of java
puzzlers. This does not mean generics is bad. Similarly, just because
closures will enable whole books of new java puzzlers (especially BGGA
closures - or rather, closures that support shorter syntax, function
types, and integrated escape-into-lexical-scope features, which
currently only BGGA is chasing without any reservations) does not mean
they should be discarded out of hand.

It does of course mean that a lot of thought has to go into it.

On Mar 11, 7:01 pm, Alexey Zinger <inline_f...@yahoo.com> wrote:
> 1992 Kawasaki EX500http://azinger.blogspot.comhttp://bsheet.sourceforge.nethttp://wcollage.sourceforge.net

Alexey Zinger

unread,
Mar 15, 2008, 4:20:46 PM3/15/08
to java...@googlegroups.com
Agreed, Reinier.  It's indeed easy to fall into the comfort of old knowledge and yell at the new kids to get off your unkempt lawn, satisfying as it may be...

Reinier Zwitserloot <rein...@gmail.com> wrote:

Many good points, Alexey. A few notes:

I don't think its fair to presume a feature to be a bad idea just
because it generates a whole new volume of java puzzlers. Generics are
clearly worth it. I'm aware that generics are somewhat controversial
and there are those who feel they were a bad idea, but I don't. I am
sympathetic to any attempt to improve them (e.g. reifing them), but
given the restrictions of backwards compatibility, generics as
implemented in 1.5 was the only way, and it has made java a better
language.

It has also created a large and extremely complicated batch of java
puzzlers. This does not mean generics is bad. Similarly, just because
closures will enable whole books of new java puzzlers (especially BGGA
closures - or rather, closures that support shorter syntax, function
types, and integrated escape-into-lexical-scope features, which
currently only BGGA is chasing without any reservations) does not mean
they should be discarded out of hand.

It does of course mean that a lot of thought has to go into it.

On Mar 11, 7:01 pm, Alexey Zinger wrote:
> --- Reinier Zwitserloot wrote:
> > > There's similar issues with variable scope.  Currently, anonymous inner
> > classes
> > > can see variables declared in enclosing scope, but only if they're declared
> > > final.  It's still possible to make them variable, but it quickly gets
> > ugly:
>
> > Instead of an array you can also write a Pointer class which is

Michael Neale

unread,
Mar 18, 2008, 12:45:26 AM3/18/08
to The Java Posse
I saw an example Neal Gafter came up with showing a very simple use of
closures to simplify IO streams:

http://www.artima.com/forums/flat.jsp?forum=276&thread=227036

The short:
Turn this mess:
FileInputStream input = new FileInputStream(fileName);
try {
// use input
} finally {
try {
input.close();
} catch (IOException ex) {
logger.log(Level.SEVERE, ex.getMessage(), ex);
}
}

Into:

with (FileInputStream input : new FileInputStream(fileName)) {
// use input
}

"with" is actually a static import, which is a method that takes the
stream, and then a block (closure).

Not bad.

On Mar 16, 6:20 am, Alexey Zinger <inline_f...@yahoo.com> wrote:
> Agreed, Reinier. It's indeed easy to fall into the comfort of old knowledge and yell at the new kids to get off your unkempt lawn, satisfying as it may be...
>
> > 1992 Kawasaki EX500http://azinger.blogspot.comhttp://bsheet.sourceforge.nethttp://wcolla...
>
> > ___________________________________________________________________________ _________
> > Never miss a thing. Make Yahoo your home page.http://www.yahoo.com/r/hs
>
> Alexey
> 2001 Honda CBR600F4i (CCS)
> 1992 Kawasaki EX500http://azinger.blogspot.comhttp://bsheet.sourceforge.nethttp://wcollage.sourceforge.net
>
> ---------------------------------

blake

unread,
Mar 18, 2008, 2:03:34 AM3/18/08
to The Java Posse
It is totally true: That is an extremely appealing example.

On the other hand, the cost is also pretty high: you would be able to
create entirely new languages, within Java.

Guess what this (nearly legal) code does?

sometimesExecuteThisBlock() {
while (true) { System.out.println("invisibility, that's what I
say"); }
}

You guessed it! It prints "Hello World" once, and terminates
normally.

-blake
> > 1992 Kawasaki EX500http://azinger.blogspot.comhttp://bsheet.sourceforge.nethttp://wcolla...

Peter Becker

unread,
Mar 18, 2008, 6:38:43 AM3/18/08
to java...@googlegroups.com
While I still haven't decided if I'm for or against adding closures to Java, I think your example could be done like this as well:

  someObject.sometimesExecuteThisRunnable(new Runnable(){
    public void run() {

       while (true) { System.out.println("invisibility, that's what I say"); }
    });

Even if you have this:

  Logger.log("Starting...");

it might wipe your harddisk instead.

Or do I miss your point?

  Peter

Reinier Zwitserloot

unread,
Mar 18, 2008, 10:03:35 AM3/18/08
to The Java Posse
Wow, that example is horrifying.

It really is time people stop writing example code that so
spectacularly bollockses up exceptions. You should NEVER log an
exception and let code execution just continue!

If the exception happends, code should not continue running unless the
encompassing block explicitly says its allright.

On Mar 18, 11:38 am, "Peter Becker" <peter.becker...@gmail.com> wrote:
> While I still haven't decided if I'm for or against adding closures to Java,
> I think your example could be done like this as well:
>
>   someObject.sometimesExecuteThisRunnable(new Runnable(){
>     public void run() {
>        while (true) { System.out.println("invisibility, that's what I say");}
>
>     });
>
> Even if you have this:
>
>   Logger.log("Starting...");
>
> it might wipe your harddisk instead.
>
> Or do I miss your point?
>
>   Peter
>
> > > > Never miss a thing.  ...
>
> read more »

blake

unread,
Mar 18, 2008, 10:33:39 AM3/18/08
to The Java Posse
No, you have my point exactly.

...and, honestly, I'm not sure why I find it so scary. After all,
this code has pretty much the same qualities:

if (sometimesExecuteThisBlock) {
// the usual
}

A matter of degrees, to be sure. The same thing happens when
application is based on a templating framework: you can have a heck of
a time figuring out where stuff is actually happening.

I feel I can read both the example above, and your example, and have
some idea of what they do. The above will not print "Hello world" and
exit. Yours might. On the other hand yours never claims that the
code in the Runnable is executed, so I'm not entirely surprised if it
isn't.

Java is getting long in the tooth. Maybe the best thing it could do,
in its dotage, is go for a really, really interesting experiment like
this. On the other hand, I doubt that it will be a matter of just "a
few new Puzzlers".

-blake

On Mar 18, 3:38 am, "Peter Becker" <peter.becker...@gmail.com> wrote:
> While I still haven't decided if I'm for or against adding closures to Java,
> I think your example could be done like this as well:
>
>   someObject.sometimesExecuteThisRunnable(new Runnable(){
>     public void run() {
>        while (true) { System.out.println("invisibility, that's what I say");}
>
>     });
>
> Even if you have this:
>
>   Logger.log("Starting...");
>
> it might wipe your harddisk instead.
>
> Or do I miss your point?
>

Kevin Wong

unread,
Mar 18, 2008, 11:24:43 AM3/18/08
to The Java Posse
Incidentally, I would use IOUtils#closeQuietly in Apache Commons IO to
make that code more terse:

FileInputStream input = new FileInputStream(fileName);
try {
// use input
} finally {
IOUtils.closeQuietly(input);
}

Normally I don't approve of swallowing exceptions, but there's usually
not much you can do about exceptions thrown when closing streams.
> > 1992 Kawasaki EX500http://azinger.blogspot.comhttp://bsheet.sourceforge.nethttp://wcolla...

Peter Becker

unread,
Mar 18, 2008, 5:47:54 PM3/18/08
to java...@googlegroups.com
I assume you are referring to Michael's example, not mine (I was confused at first).

What exactly would you do in a scenario where some resource fails to close properly (be it an IO stream, a database connection or anything else)? I can't say I like doing the try and log failure approach, but I haven't seen a better solution yet. And I wouldn't even pick Level.SEVERE for that, WARNING seems much more appropriate: something went wrong, but chances are that it's not that horrible for us. Maybe some code we called illegally closed the resource for us but as long as we don't try to use it anymore that is not a severe issue for execution. Maybe the harddisk died on us, but that gets severe only if we try to read/write again, not if the close was the last thing we tried.

  Peter

Christian Catchpole

unread,
Mar 18, 2008, 7:59:38 PM3/18/08
to The Java Posse
On Mar 19, 1:24 am, Kevin Wong <kevin.peter.w...@gmail.com> wrote:
> Normally I don't approve of swallowing exceptions, but there's usually
> not much you can do about exceptions thrown when closing streams.

yeah, you have 2 exceptions and the close exception is the lesser of
the 2 evils. :)

Reinier Zwitserloot

unread,
Mar 19, 2008, 7:38:13 AM3/19/08
to The Java Posse
Whoops, I misread that code example and thought the log-and-ignore was
being done to any IOException during the reading of the file. log-and-
ignore treatment is being given to CLOSING the file. I don't see the
point to doing that, but it's not nearly as big of a violation.

I don't see the point because you still have to deal with IOExceptions
one way or another, and as a read-only file throwing an IOException
during close, after reading it as far as you wanted to take it worked
out fine, is basically impossible. It's a bit like giving the log-and-
ignore treatment to the UnsupportedEncodingException thrown by
String.getBytes("UTF-8"). If you do it to avoid having to declare or
try/catch the exception, well, okay. It's not the nicest way of
handling that (rewrap as AssertionError would probably be better). But
if you're throwing it/ dealing with it anyway, you can just ignore it.
In fact, I would say that if for whatever reason the file close
operation does throw an exception, you should definitely treat it as a
real exception.



On Mar 19, 12:59 am, Christian Catchpole <christ...@catchpole.net>
wrote:

Christian Catchpole

unread,
Mar 19, 2008, 7:59:11 AM3/19/08
to The Java Posse
Perhaps its a bad example for a closure because its an example of a
finally statement which throws itself. Or is it a good example by
pointing out the complication?
Reply all
Reply to author
Forward
0 new messages