[racket] Help With a Macro (tricky?)

From: Hal Henke (halhenke at gmail.com)
Date: Fri Jan 13 02:20:07 EST 2012

Hi Marjin,

Firstly - wow sorry about all that html :-(

For anyone still interested that first post should have read:

"In other words instead of typing all this:

(class object%
  (init size)                ; initialization argument
  (define current-size size) ; field
  (define/public (get-size)

I wanted to be able to write something like:

  (init+ size)

that would expand to something like:

  (init size)         ; initialization argument
  (define size+ size) ; field
  (define/public (size++)

even better would be an expansion of (init+ size) to:

 (init size++)         ; initialization argument
  (define size+ size++) ; field
  (define/public (size)

Secondly thanks very much for your help - your example worked great.
Only thing is - I'm having trouble generalising the macro to handle
multiple arguments. The real problem seems to be that anytime the term
init, init-field, define/public is mentioned inside a class, inside a
list or any other type of s-expression an error gets thrown

"init-field: use of a class keyword is not in a class top-level in:
(init-field _field_)"

so 'm having real difficulty trying to get a macro that spits out an
arbitrary number of init field define-public pairs e.g.

(class object%
    (init-field a1)
    (define/public (get-a1) a1)
    (init-field a2)
    (define/public (get-a1) a2)
      etc... )

So far ive been mucking round with something like this to no success:

(define-syntax my-big-class
  (lambda (stx)
    (syntax-case stx ()
      ((_ _field_ ...)
       #'(class object%
           (my-init _field_)

(define-syntax my-init
  (lambda [stx]
    (syntax-case stx ()
      ([_ _field_]
              #f (string->symbol
                    (syntax->datum #'_field_)))))))
         #'[(init-field _field_)
            (define/public (getter) _field_)])))))

I'm sure theres a simple way around this that I'm missing.

Thanks again,


On Wed, Jan 11, 2012 at 9:14 PM, Marijn <hkBst at gentoo.org> wrote:
> Hash: SHA1
> On 11-01-12 04:44, Hal Henke wrote:
> > Hi Racketeers,
> Hi Hal,

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

Posted on the users mailing list.