|
|
||
Rémi Forax's BlogAugust 2006 ArchivesSyntax of closurePosted by forax on August 31, 2006 at 06:37 AM | Permalink | Comments (12)In forum (fora) and blogs, i have often seen that closures are compared to anonymous classes in order to reject the proposed syntax of closure. In this entry, i try to show up why the closure syntax is such as it is by explaining the differences with the anonymous class syntax. Let me introduce an example that sort a list of integers in reverse order. There are two codes, one written with an anonymous class and the other written with a closure using the closure convertion. The code using a closure:
List<Integer> list=Arrays.asList(666,7,12);
Collections.sort(list,int(Integer i1,Integer i2) {
if (i1<i2)
return 1;
else
if (i2<i1)
return -1;
return 0;
});
And the code using an anonymous class:
List<Integer> list=Arrays.asList(666,7,12);
Collections.sort(list,new Comparator<Integer>(){
public int compareTo(Integer i1,Integer i2) {
if (i1<i2)
return 1;
else
if (i2<i1)
return -1;
return 0;
}
});
I've found five differences and all have a reason so i don't see why people want to change the proposed syntax. A step by step comparison
I hope this entry will reconcile the grimpies with the proposed
syntax.
Is closure swing ?Posted by forax on August 29, 2006 at 04:08 PM | Permalink | Comments (9)Yes, this is another entry about closure :)
In the closure proposal, the section "Closure conversion"
describes how to use a closure instead of an anonymous class.
So let see if these rules are sufficient to use closures in order to implement AWT/Swing callbacks. Implementing an ActionListener ActionListener corresponds to a component default action, it's a one method interface, the method actionPerformed takes an ActionEvent that contains among other things the component that received the event.
public interface ActionListener {
void actionPerformed(ActionEvent e);
}
So the client code can be this one :
JButton button=new JButton("Ok");
button.addActionListener(() {
button.setText("Ko");
});
Oh no !!!
JButton button=new JButton("Ok");
button.addActionListener((ActionEvent notUsed) {
button.setText("Ko");
});
The moral It could be a good idea to add a closure conversion rule that permits parameters omission. Perhaps this rule can be extended to allow the omission of the last parameters from the right. What do you think about that ? Function that does not return normallyPosted by forax on August 26, 2006 at 08:04 AM | Permalink | Comments (14)It's a recurring problem, you have a code that always generates an exception
public void throwIOException(int code) throws IOException {
throw new IOException(IO.getMessage(code));
}
and you use it in a method like this :
public int read() throws IOException {
int value=readAByte()
if (value!=-1)
return value;
throwIOException(IO.errorCode);
}
Because there is no way to say to the compiler something like "hey, the method throwIOEXception doesn't return", the compiler emit an error because the method read() could return without a value. In the now famous closure proposal, there is a small section titled "The type of null" that i understand like this: if you use null as return type, you can indicate that the method never return.
public null throwIOException(int code) throws IOException {
throw new IOException(getMessage(code));
}
Pretty cool ! update: see Function that does not return normally II (the return) for the part2 of this entry. Closure and performancePosted by forax on August 24, 2006 at 05:09 AM | Permalink | Comments (12)I've read the proposal about function types and closures and i have noticed that the invocation of a function type will use the newly introduced bytecode invokedynamic (the gilad blog about invokedynamic) and i think i know why !
So let me introduce a small example of closure, the method
transform applies a transformation
on each item of an array and store the result in the same array.
static CharSequence[] transform(CharSequence(CharSequence) transformation,CharSequence... array) {
for(int i=0;i<array.length;i++) {
array[i]=transformation(array[i]);
}
return array;
}
The following code applies an identity transformation :
CharSequence(CharSequence) identity = (CharSequence seq) {return seq; };
CharSequence[] seqs=transform(identity,"2","3");
System.out.println(Arrays.toString(seqs));
So why closure can't use a classical call (invokevirtual)
instead of a invokedynamic call,
because the proposal defines subtyping rules between closures.
String(Object) bang = (Object o) {return "!"+o; };
CharSequence[] seqs2=transform(bang,"2","3");
System.out.println(Arrays.toString(seqs2));
So in the method transform, the call to transformation can call a function type with a different signature that the one declared, that's why invokedynamic must be used here.
So why using invokedynamic is important, it's because it can
hurt performance, invoking a method without the same signature
is more complex than a simple call.
Meta protocol mix in JDBC 4.0Posted by forax on August 02, 2006 at 02:18 AM | Permalink | Comments (6)While reading the JDBC 4.0 spec, i found a meta protocol mix in the way the spec specifies how to create an empty DataSet using the newly introduced query interface mecanism. But before let me introduce the context : JDBC 4JDBC 4.0 introduces a new way to map a class to a result of a JDBC Query automagically. It's not a real O/R Mapper like hibernate or the one describes by the EJB3 spec because by example inheritance or relationship between tables are not managed. It's just a toy O/R Mapper that ease the repetitive task of manually copying data from a ResultSet to object fields.
By example, the class below describes a table of authors and
the inner-interface Author.Query describes queries that
can be applied on this table.
public class Author {
private int id;
private String firstname;
private String lastname;
public Author() {
// used by JDBC mapper
}
public int getId() {
return id;
}
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public static final String DDL=
"create table author(\n" +
" id INTEGER NOT NULL\n"+
" PRIMARY KEY GENERATED ALWAYS AS IDENTITY\n"+
" (START WITH 1, INCREMENT BY 1),\n" +
" firstname VARCHAR(128) NOT NULL UNIQUE,\n"+
" lastname VARCHAR(128) NOT NULL UNIQUE"+
")";
public interface Query extends BaseQuery {
@Select(sql="SELECT * FROM author")
DataSet
To specify a query, the spec introduces two annotations
@Select (SELECT)or @Update (UPDATE, ALTER, DELETE etc)
but no annotation for operations like CREATE or DROP.
Connection con=... Author.Query query=con.createQueryObject(Author.Query.class); DatatSet [I've updated the following section, Rémi]
Now, the spec introduces a way
to create an empty DataSet automatically without using
a query SELECT (section 19.4.2.6).
What is a meta protocol ?
What if a method named "create" is tagged by an annotation
@Select ?
oups, there is a meta protocol mix.
| ||
|
|