[racket] Advice on a macro for mutating structs

From: Tom McNulty (tom at cetiforge.com)
Date: Thu Jul 28 15:59:59 EDT 2011

Thanks Matthias, thats a lot cleaner than my version.

On 2011-07-28, at 1:19 PM, Matthias Felleisen wrote:

> 
> 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))
>         (cond
>           [(boolean? get-set-f) (raise-syntax-error #f "unknown field-name: ~a" stx)]
>           [else 
>            (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.