To use dot notation like this, you'll need to define a new #lang
language, with its own reader. There are several tools to help with this, and I'll be using one of them, syntax/module-reader
, to define #lang send-dot
, which once defined can be used like this:
#lang send-dot
(define o
(new (class object% (super-new)
(define/public (f x) x))))
(o.f "hellooo")
In the latest snapshot version of Racket, you can use the read-cdot
option. Make sure you're on the latest snapshot version, since in 6.6, it's completely broken.
One way to define a #lang
is by declaring a reader
submodule. Make a directory called send-dot
, and add a file called main.rkt
. This file should provide everything from racket.
#lang racket
(provide (all-from-out racket))
This doesn't define a #lang
yet. But to try it out, you can go to DrRacket's File menu, click on Package Manager, and in the Package Source field, enter the path to the send-dot
directory. Once you do that, you should be able to use #lang s-exp send-dot
in another file just like you would #lang racket
.
To define a reader for this language and make it a real #lang
language, you can add a reader
submodule that uses syntax/module-reader
as its language.
#lang racket
(provide (all-from-out racket))
;; This submodule defines the reader for the language
(module reader syntax/module-reader
send-dot)
Now you should be able to use #lang send-dot
just like #lang racket
.
Now you need to do two more things. One, turn on the read-cdot
option so that (o.method args ...)
is translated to ((#%dot o method) args ...)
, and Two, define a #%dot
macro so that ((#%dot o method) args ...)
is equivalent to (send o method args ...)
.
For the first thing, you can use the #:wrapper1
option, using parameterize
to turn read-cdot
on.
#lang racket
(provide (all-from-out racket))
;; This submodule defines the reader for the language
(module reader syntax/module-reader
send-dot
#:wrapper1 (lambda (thunk)
;; turns on the read-cdot option,
;; which will turn o.method into (#%dot o method),
;; and (o.method args ...) into ((#%dot o method) args ...)
(parameterize ([read-cdot #true])
(thunk))))
For the second thing, you need to define a #%dot
macro. o.method
, or (#%dot o method)
, needs to be a function that calls the method, so you can use (lambda args (send/apply o method args))
.
#lang racket
(provide #%dot (all-from-out racket))
;; transforms (#%dot o method) into a function that calls the method
;; so that ((#%dot o method) args ...) will be roughly equivalent to
;; (send o method args ...)
(define-syntax-rule (#%dot obj-expr method-id)
(let ([obj obj-expr])
(lambda args (send/apply obj method-id args))))
;; This submodule defines the reader for the language
(module reader syntax/module-reader
send-dot
#:wrapper1 (lambda (thunk)
;; turns on the read-cdot option,
;; which will turn o.method into (#%dot o method),
;; and (o.method args ...) into ((#%dot o method) args ...)
(parameterize ([read-cdot #true])
(thunk))))
Now you should be able to use #lang send-dot
like this:
#lang send-dot
(define o
(new (class object% (super-new)
(define/public (f x) x))))
(o.f "hellooo")