This is the mail archive of the kawa@sources.redhat.com 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]

Alternate syntax for field access/method calls


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
 



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