This is the mail archive of the
kawa@sourceware.org
mailing list for the Kawa project.
Re: easier Kawa object building with Swing example
- From: Jamison Hope <jrh at theptrgroup dot com>
- To: kawa at sourceware dot org
- Date: Mon, 11 Oct 2010 22:08:54 -0400
- Subject: Re: easier Kawa object building with Swing example
- References: <4CA602A3.5060701@bothner.com>
On Oct 1, 2010, at 11:47 AM, Per Bothner wrote:
For a while Kawa has supported:
(MyClass keyword1: value1 ... kewordN: valueN)
as shorthand for:
(let ((tmp (make MyClass)))
(set! tmp:keyword1 value1)
...
(set! tmp:keywordN valueN)
tmp)
where
(set! tmp:keywordI valueI)
could compile to either setting a field or calling a setKeywordI
method.
I have a number of setters which have the general form:
public <ObjType> setFoo(<FooType> arg) {
this.foo = arg;
return this;
}
It's a style I picked up from Objective-C which has proven handy in
constructs like
"container.add(new ObjType().setFoo(foo).setBar(bar));"
letting me avoid assigning my new object to a local variable just to
call some methods on it before handing it off to something else. It's
roughly the Java equivalent of this Kawa keyword setter style.
Anyway, I have found that Kawa's keyword style fails with my setters:
$ cat test/A.java
package test;
public class A {
private int x;
private String y;
public A setX(int arg) { x = arg; return this; }
public int getX() { return x; }
public A setY(String arg) { y = arg; return this; }
public String getY() { return y; }
public String toString() { return super.toString() + ",x="+x
+",y="+y; }
}
$ cat test/B.java
package test;
public class B extends A {
private float z;
public B setZ(float arg) { z = arg; return this; }
public float getZ() { return z; }
public String toString() { return super.toString() + ",z="+z; }
}
$ javac test/A.java test/B.java
$ java kawa.repl
#|kawa:1|# (define a (test.A))
#|kawa:2|# (define b (test.B))
#|kawa:3|# (define a (test.A x: 42))
exception while initializing module atInteractiveLevel$3
at gnu.expr.ModuleContext.findInstance(ModuleContext.java:84)
at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:274)
at gnu.expr.ModuleExp.evalModule(ModuleExp.java:185)
at kawa.Shell.run(Shell.java:281)
at kawa.Shell.run(Shell.java:194)
at kawa.Shell.run(Shell.java:175)
at kawa.repl.main(repl.java:847)
Caused by: java.lang.VerifyError: (class: atInteractiveLevel$3,
method: run signature: (Lgnu/mapping/CallContext;)V) Incompatible
object argument for function call
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
at java.lang.Class.getDeclaredField(Class.java:1880)
at gnu.expr.ModuleContext.findInstance(ModuleContext.java:74)
... 6 more
#|kawa:4|# (test.A x: 42)
test.A@76497934,x=42,y=null
#|kawa:5|# (define b (test.B z: 1.5))
exception while initializing module atInteractiveLevel$5
at gnu.expr.ModuleContext.findInstance(ModuleContext.java:84)
at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:274)
at gnu.expr.ModuleExp.evalModule(ModuleExp.java:185)
at kawa.Shell.run(Shell.java:281)
at kawa.Shell.run(Shell.java:194)
at kawa.Shell.run(Shell.java:175)
at kawa.repl.main(repl.java:847)
Caused by: java.lang.VerifyError: (class: atInteractiveLevel$5,
method: run signature: (Lgnu/mapping/CallContext;)V) Incompatible
object argument for function call
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
at java.lang.Class.getDeclaredField(Class.java:1880)
at gnu.expr.ModuleContext.findInstance(ModuleContext.java:74)
... 6 more
#|kawa:6|# (test.B z: 1.5)
test.B@3d9360e2,x=0,y=null,z=1.5
#|kawa:7|# (test.B z: 1.5 x: 42)
test.B@6766afb3,x=42,y=null,z=1.5
#|kawa:8|# (test.B x: 42 z: 1.5)
exception while initializing module atInteractiveLevel$8
at gnu.expr.ModuleContext.findInstance(ModuleContext.java:84)
at gnu.expr.ModuleExp.evalModule2(ModuleExp.java:274)
at gnu.expr.ModuleExp.evalModule(ModuleExp.java:185)
at kawa.Shell.run(Shell.java:281)
at kawa.Shell.run(Shell.java:194)
at kawa.Shell.run(Shell.java:175)
at kawa.repl.main(repl.java:847)
Caused by: java.lang.VerifyError: (class: atInteractiveLevel$8,
method: run signature: (Lgnu/mapping/CallContext;)V) Incompatible
object argument for function call
at java.lang.Class.getDeclaredFields0(Native Method)
at java.lang.Class.privateGetDeclaredFields(Class.java:2291)
at java.lang.Class.getDeclaredField(Class.java:1880)
at gnu.expr.ModuleContext.findInstance(ModuleContext.java:74)
... 6 more
and so on. I find it especially interesting that in some cases,
assigning to a variable triggers the Exception
(e.g. "(test.A x: 42)" works, but "(define a (test.A x: 42))" blows up).
If I change setX(), setY(), and setZ() all to return void instead,
then Kawa works as expected:
$ java kawa.repl
#|kawa:1|# (define a (test.A))
#|kawa:2|# (define b (test.B))
#|kawa:3|# (define a (test.A x: 42))
#|kawa:4|# (test.A x: 42)
test.A@76497934,x=42,y=null
#|kawa:5|# (define b (test.B z: 1.5))
#|kawa:6|# (test.B z: 1.5)
test.B@3d9360e2,x=0,y=null,z=1.5
#|kawa:7|# (test.B z: 1.5 x: 42)
test.B@6766afb3,x=42,y=null,z=1.5
#|kawa:8|# (test.B x: 42 z: 1.5)
test.B@5975d6ab,x=42,y=null,z=1.5
But then I lose functionality on the Java side, so that's not really
desirable. Any ideas why non-void-return setters would break
(let ((tmp (make MyClass)))
(set! tmp:keyword1 value1)
...
(set! tmp:keywordN valueN)
tmp)
?
Thanks,
Jamie
Oh, by the way, Kawa is being noisy about unboxing booleans:
$ java kawa.repl
#|kawa:1|# (javax.swing.JPanel visible: #f)
/dev/stdin:1:1: warning - type java.lang.Boolean is incompatible
with required type boolean
javax.swing.JPanel[,
0,0,0x0
,invalid
,hidden
,layout
=
java
.awt
.FlowLayout
,alignmentX
=
0.0
,alignmentY
=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]
That's probably analogous to the conversions between integer and the
numeric primitives I brought up last week.
--
Jamison Hope
The PTR Group
www.theptrgroup.com