[racket] Help With a Macro (tricky?)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 11-01-12 04:44, Hal Henke wrote:
> Hi Racketeers,
Hi Hal,
> Just getting started in the whole Racket thing - it seems like the
> nicest Lisp around at this point in time. A big reason for me
> wanting to get to know Lisp/Scheme/Racket was to play around with
> macros and it seems like Racket takes the idea to its logical
> conclusion going beyond hygenic macros with its whole language
> building features. However I have to say I have found it a little
> difficult to fully get my head around some of the ideas (phase
> levels etc) so I suppose i could at least understand why some
> people yearn for the simplicity of "defmacro" despite its flaws. I
> think i just need to plow through the references some more.
>
> Anyway for mostly self-educational purposes I was trying to get a
> particular macro working and cant seem to do it. The inspiration
> behind it was that I was looking at the Racket Object System and I
> kind of felt like there was a little less typing to get a class
> going. I'm also a bit of a fan of light feeling OO systems like in
> Python that dont really care about enforcing privacy and just
> wanted to give the class declaration a name and then have a public
> variable/property available without the need to write 3 lines. In
> other words instead of typing all this:
>
> (class<http://docs.racket-lang.org/reference/createclass.html#(form._((lib._racket/private/class-internal..rkt)._class))>
>
>
object%<http://docs.racket-lang.org/reference/createclass.html#(def._((lib._racket/private/class-internal..rkt)._object~25))>
> (init<http://docs.racket-lang.org/reference/createclass.html#(form._((lib._racket/private/class-internal..rkt)._init))>
>
>
size) ; initialization argument
> (define<http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))>
>
>
current-size size) ; field
> (define/public<http://docs.racket-lang.org/reference/createclass.html#(form._((lib._racket/private/class-internal..rkt)._define/public))>
>
>
(get-size) current-size) .............
This was a bit difficult to read, but I deduced that you meant
something like:
(define class1%
(class object%
(super-new)
(init-field size)
(define/public (get-size) size) ))
Look it works:
(define class1 (new class1% (size 1)))
(send class1 get-size)
> I wanted to be able to write something like:
>
> (init+ size)
>
> that would expand to something like:
>
> (init<http://docs.racket-lang.org/reference/createclass.html#(form._((lib._racket/private/class-internal..rkt)._init))>
>
>
size) ; initialization argument
> (define<http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))>
>
>
size+ size) ; field
> (define/public<http://docs.racket-lang.org/reference/createclass.html#(form._((lib._racket/private/class-internal..rkt)._define/public))>
>
>
(size++) size+)
>
> even better would be an expansion of (init+ size) to:
> (init<http://docs.racket-lang.org/reference/createclass.html#(form._((lib._racket/private/class-internal..rkt)._init))>
>
>
size++) ; initialization argument
> (define<http://docs.racket-lang.org/reference/define.html#(form._((lib._racket/private/base..rkt)._define))>
>
>
size+ size++) ; field
> (define/public<http://docs.racket-lang.org/reference/createclass.html#(form._((lib._racket/private/class-internal..rkt)._define/public))>
>
>
(size) size+)
>
> so that I had a public accesssor method that had the same name as
> the original declaration.
I hope you would then be happy to be able to write:
(define fast-class1% (fast-class size))
(define fast1 (new fast-class1% (size 2)))
(send fast1 get-size)
To make it work you need something like this macro:
(define-syntax fast-class
(lambda (stx)
(syntax-case stx ()
((_ _field_)
(with-syntax
((getter
(datum->syntax
#f (string->symbol
(string-append
"get-"
(symbol->string
(syntax->datum #'_field_)))))))
#'(class object%
(super-new)
(init-field _field_)
(define/public (getter) _field_)) )))))
Possibly there is some better way to construct the getter identifier.
If you want to stay within syntax-rules, then you have to make the
getter an argument of your macro like so:
(define-syntax fast-class2
(syntax-rules ()
((_ _field_ _getter_)
(class object%
(super-new)
(init-field _field_)
(define/public (_getter_) _field_)))))
(define fast-class2% (fast-class2 size get-size))
(define fast2 (new fast-class2% (size 3)))
(send fast2 get-size)
Hope that helps,
Marijn
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEYEARECAAYFAk8NYRAACgkQp/VmCx0OL2xZngCdHS9TXoe5pDqo4FwUGr0lRQHO
4q4AoK+B362A/ZilqGQhMIj8e/pR9Bpn
=LrX8
-----END PGP SIGNATURE-----