[racket] Advice on a macro for mutating structs

From: Matthias Felleisen (matthias at ccs.neu.edu)
Date: Thu Jul 28 15:19:45 EDT 2011

You could fake it: 

  (require (for-syntax syntax/parse))

  ;; Syntax SyntaxList SyntaxList -> [Listof (list String Syntax Syntax)]
  ;; create association list mapping field names to getters and setters [option]
  (define-for-syntax (field-association-list sn getters setters)
    (define sn-str (+ (string-length (symbol->string (syntax->datum sn))) 1))
    (define getters-lst (syntax->list getters))
    (define setters-lst (syntax->list setters))
    (for/list ((x getters-lst) (y setters-lst))
      `(,(substring (symbol->string (syntax->datum x)) sn-str) ,x ,y)))
  (define-syntax (increment! stx)
    (syntax-parse stx
      [(_ s sn:id fn:id i)
       (with-syntax ([(_ _ _ getters setters _) (extract-struct-info (syntax-local-value #'sn))])
         (define gets-sets (field-association-list #'sn #'getters #'setters))
         (define get-set-f (assoc (symbol->string (syntax-e #'fn)) gets-sets))
           [(boolean? get-set-f) (raise-syntax-error #f "unknown field-name: ~a" stx)]
            (define-values (_ getter setter) (apply values get-set-f))
            (if (boolean? setter)
                (raise-syntax-error #f (format "~s not mutable" (syntax-e #'fn)) stx)
                #`(#,setter s (+ (#,getter s) i)))]))]
      [(increment! s sn fn) #'(increment! s sn fn 1)]))

On Jul 28, 2011, at 3:08 PM, Tom McNulty wrote:

> On 2011-07-28, at 12:43 PM, Eli Barzilay wrote:
>> 7 minutes ago, Matthias Felleisen wrote:
>>> 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.
>> Ah, you're right.
>>> 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:
> Matthias: Sorry I worded that poorly.  I was looking to retrieve the accessors and mutators from the structure and field names in the macro, but that information is not retained.  
>> That's how Tom started, and I didn't follow the intention of using the
>> field name and suggested using the struct info.
>> But the real thing that you (Tom) are fighting with is trying to use
>> field names, where the struct info is disregarding that and keeps
>> around just the getter and setter names. 
> Other than possibly better error messages, I'm not sure then that the struct-info approach provides much (any?) benefit; for it still relies on knowing the accessor name.  It also seems that accessors/mutators that do not follow the usual [set-]struct-field naming seem to be a rarity (certainly in my code).
>> Looks to me like a better
>> approach would be to use the getter names instead -- possibly with a
>> macro that makes more convenient getters?
> I thought about this approaching, using something similar to the key-word structures here, http://lists.racket-lang.org/users/archive/2010-December/043340.html
> but decided it'd be better to make something that works with vanilla structs.  
> Thanks, 
> - Tom.
>> -- 
>>         ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
>>                   http://barzilay.org/                   Maze is Life!

Posted on the users mailing list.