[racket] Help With a Macro (tricky?)
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 13-01-12 08:20, Hal Henke wrote:
> Hi Marjin,
>
> Firstly - wow sorry about all that html :-(
No problem.
> 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_)"
It's complaining about your using `init-field' outside of `class'.
> 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:
Your mucking is very familiar and reminds me of my own struggles in
learning syntax-case.
> (define-syntax my-big-class (lambda (stx) (syntax-case stx () ((_
> _field_ ...) #'(class object% (super-new) (my-init _field_)
> ...)))))
Your mistake is one I have made myself many times: you call my-init as
if it were a function, but macro expansion doesn't work like function
calling. The `class' macro will be the one in charge after my-big-class.
> (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_)])))))
Here there is no enclosing `class' thus things like `init-field' are
errors.
> I'm sure theres a simple way around this that I'm missing.
I always find it tricky when to convert from syntax to normal scheme,
when to convert back and the difference between a list of syntax and a
syntax object that contains a list... but in the end I managed to find
the right mix:
(define-syntax fast-class
(lambda (stx)
(syntax-case stx ()
((_ _field_ ...)
(with-syntax
(((_getter_ ...)
(datum->syntax
#f
(map
(lambda (f)
(string->symbol
(string-append
"get-"
(symbol->string f))))
(syntax->datum #'(_field_ ...)) )) ))
#'(class object%
(super-new)
(init-field _field_ ...)
(define/public (_getter_) _field_) ...) )))))
(define fast-class1% (fast-class size weight))
(define fast1 (new fast-class1% (size 2) (weight 200)))
(send fast1 get-size)
(send fast1 get-weight)
> Thanks again,
You're welcome,
Marijn
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
iEUEARECAAYFAk8QCYAACgkQp/VmCx0OL2wXpQCY8ctNFD8lcEQOwzNP6FFPjxrT
QACdFUXqhHrwEsgW79d0PPIukZHDHyc=
=+9Oa
-----END PGP SIGNATURE-----