[racket] Help With a Macro (tricky?)
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)
current-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++)
size+)
even better would be an expansion of (init+ size) to:
(init size++) ; initialization argument
(define size+ size++) ; field
(define/public (size)
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%
(super-new)
(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%
(super-new)
(my-init _field_)
...)))))
(define-syntax my-init
(lambda [stx]
(syntax-case stx ()
([_ _field_]
(with-syntax
((getter
(datum->syntax
#f (string->symbol
(string-append
"get-"
(symbol->string
(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,
Hal
On Wed, Jan 11, 2012 at 9:14 PM, Marijn <hkBst at gentoo.org> wrote:
>
> -----BEGIN PGP SIGNED MESSAGE-----
> 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