This is the mail archive of the
kawa@sources.redhat.com
mailing list for the Kawa project.
Alternate syntax for field access/method calls
- From: "Dominique Boucher" <dominique dot boucher at nuecho dot com>
- To: <kawa at sources dot redhat dot com>
- Date: Fri, 14 Jan 2005 14:12:45 -0500
- Subject: Alternate syntax for field access/method calls
- Reply-to: <dominique dot boucher at nuecho dot com>
Hi,
In my Scheme code, I frequently have to access Java objects. But I sometimes
find the Kawa syntax for
accessing fields and calling methods too verbose, especially when one has to
compose calls to
'invoke' and 'field'. For example, the following Java code:
someObject.method1().method2(a, b)
has to be written in Kawa Scheme as:
(invoke (invoke someObject 'method1) 'method2 a b)
To someone coming from the Java world, this can be very hard to read.
So I decided to extend the Scheme reader to support an alternate syntax for
accessing fields
and calling methods. With this new syntax, the example becomes:
[someObject (method1) (method2 a b)]
This way, method calls look more like ordinary function calls. To access
fields, forget the parentheses:
[someObject the-field]
Note that field accesses and method calls can be combined/mixed:
[someObject the-field (method1 a b) other-field)]
This is equivalent to
someObject.theField.method1(a, b).otherField
Here is the applet example (taken from the Kawa documentation) rewritten:
(define-private last-x 0)
(define-private last-y 0)
(define (init) <void>
(let ((applet :: <java.applet.Applet> (this)))
[applet (addMouseListener
(object (<java.awt.event.MouseAdapter>)
((mousePressed (e :: <java.awt.event.MouseEvent>)) <void>
(set! last-x [e (getX)])
(set! last-y [e (getY)]))))]
[applet (addMouseMotionListener
(object (<java.awt.event.MouseMotionAdapter>)
((mouseDragged (e :: <java.awt.event.MouseEvent>)) <void>
(let ((g :: <java.awt.Graphics> [applet (getGraphics)])
(x :: <int> [e (getX)])
(y :: <int> [e (getY)]))
[g (drawLine last-x last-y x y)]
(set! last-x x)
(set! last-y y)))))))
(define (start) <void> (format #t "called start.~%~!"))
(define (stop) <void> (format #t "called stop.~%~!"))
(define (destroy) <void> (format #t "called destroy.~%~!"))
For those interested in using this syntax, here is the source code.
-----------------------------------------------
(define-simple-class <FieldOrMethodReader>
(<gnu.kawa.lispexpr.ReadTableEntry>)
(list-reader type: <gnu.kawa.lispexpr.ReaderParens>
init-value: (make <gnu.kawa.lispexpr.ReaderParens> #\[ #\]
5))
((read (lexer :: <gnu.text.Lexer>) (ch :: <int>) (count :: <int>)) ::
<Object>
(let ((obj (invoke list-reader 'read lexer ch count)))
(if (and (list? obj) (pair? obj))
(let loop ((result (car obj)) (rest (cdr obj)))
(cond
((null? rest)
result)
((symbol? (car rest))
(let ((fieldname (car rest)))
(loop `(field ,result ',fieldname) (cdr rest))))
((and (list? (car rest)) (pair? (car rest)) (symbol? (caar
rest)))
(let ((methodname (caar rest))
(args (cdar rest)))
(loop `(invoke ,result ',methodname ,@args) (cdr rest))))
(else
(error "Invalid field or method call form:" obj))))
(error "Invalid field or method call form:" obj)))))
(let ((read-table (static-field <gnu.kawa.lispexpr.ScmRead>
'schemeReadTable)))
(invoke read-table 'setBracketMode 1)
(invoke read-table 'set 91 (make <FieldOrMethodReader>)))
-----------------------------------------------
Dominique Boucher, Ph.D.
Nü Écho Inc
www.nuecho.com
Tél: (514) 861-3246 x 231