This is the mail archive of the kawa@sourceware.org mailing list for the Kawa project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: easier Kawa object building with Swing example


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




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]