[racket] writing a define-world macro
Actually, this macro doesn't quite work, because it uses the #lang
racket version of define-struct instead of the version appropriate to
whichever language the student is in: Beginning SL, Intermediate SL,
or Advanced SL.
How would I fix that?
Todd
On Sun, Jul 25, 2010 at 4:16 PM, Todd O'Bryan <toddobryan at gmail.com> wrote:
> Because it can get really annoying to have to retrofit a whole program
> when you add a bit of extra state to a world, Barry Brown first
> suggested and then I--having completely forgotten about Barry's
> suggestion--re-suggested that worlds include functional update
> functions, so that changing a single field in a world didn't require
> students to include boilerplate code to leave all the other fields
> unchanged.
>
> I think the following macro just about does this:
>
> #lang racket
> (provide define-world)
>
> (define-for-syntax (build-name id . parts)
> (datum->syntax
> id
> (string->symbol
> (apply string-append
> (map (lambda (p)
> (cond
> [(syntax? p) (symbol->string (syntax-e p))]
> [(symbol? p) (symbol->string p)]
> [(string? p) p]))
> parts)))
> id))
>
> (define-for-syntax (updater id fields field)
> (let ([name (build-name id id '- 'update- field)]
> [instance (build-name id 'a- id)]
> [constructor (build-name id 'make- id)])
> `(define (,name ,instance val)
> (,constructor ,@(for/list ([f fields])
> (if (equal? f field)
> 'val
> `(,(build-name id id '- f) ,instance)))))))
>
> (define-syntax (define-world stx)
> (syntax-case stx ()
> [(_ id fields)
> (let ([field-names (syntax->list #'fields)])
> #`(begin
> (define-struct id fields)
> #,@(for/list ([f field-names])
> (updater #'id field-names f))))]))
>
> How do I provide tests, and is there any chance something like this
> could end up in 2htdp/universe?
>
> Todd
>