[racket] Advice on a macro for mutating structs

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Thu Jul 28 14:33:47 EDT 2011

On Jul 28, 2011, at 2:10 PM, Tom McNulty wrote:

> I was hoping that I could locate the getter (and setter) with just the field and structure type but that information doesn't seem to be possible. 

I don't understand your request but if you are giving me the structure name and the structure field, you can write a context-sensitive macro: 

  (require (for-syntax syntax/parse))
  (define-syntax (incr! stx)
    (syntax-parse stx 
      [(_ s st:id fd:id i) 
       (let ([setter (datum->syntax #'st (string->symbol (format "set-~a-~a!" (syntax-e #'st) (syntax-e #'fd))))])
         #`(#,setter s i))]))
  (struct box ((x #:mutable)))
  (define b (box 1))
  (incr! b box x 2)
  (displayln (box-x b))

Problem is this blows up with the wrong error message. 

Also, you may wish to test failure cases like this: 

 (with-handlers ((exn:fail:syntax? (lambda (x) (string=? (exn-message x) "increment!: pounds not mutable"))))
    (eval '(module _a racket/base 
             (require 'increment) 
             (struct vault ([dollars #:mutable] pounds [euros #:mutable]))
             (increment! v vault pounds)))
    (displayln "test failed"))

That way you don't have to comment them out. Abstract suitably. 

Posted on the users mailing list.