[racket] Help With a Macro (tricky?)

From: Marijn (hkBst at gentoo.org)
Date: Wed Jan 11 05:14:40 EST 2012

-----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-----


Posted on the users mailing list.