[plt-dev] struct match-expander a la struct-copy

From: Jay McCarthy (jay.mccarthy at gmail.com)
Date: Wed Jun 24 14:35:46 EDT 2009

I experimented with this a little bit and didn't like it too much,
because to do it right you get into strangeness with super structures.
Can you think of some way around it?

Here's an example:

(define-struct crazy (car) #:transparent)
(define-struct (kons crazy) (car cdr) #:transparent)
(define make-kons/key (struct-keyword-constructor kons))

(make-kons/key #:crazy-car 0
               #:kons-car 1
               #:kons-cdr 2)

Here's the code for struct-keyword-constructor:

(require (for-syntax scheme/match
                     scheme/list
                     scheme/struct-info))

(define-for-syntax (fix-first l)
  (if (first l)
      l
      (rest l)))

(define-syntax (struct-keyword-constructor stx)
  (syntax-case stx ()
    [(_ struct-id)
     (unless (identifier? #'struct-id)
       (raise-syntax-error 'struct-keyword-constructor "Not an
identifier" #'struct-id))
     (match
         (syntax-local-value
          #'struct-id
          (lambda ()
            (raise-syntax-error 'struct-keyword-constructor "Not bound
syntax identifier" #'struct-id)))
       [(and (? struct-info?)
             (app extract-struct-info (list descriptor constructor
predicate (list accessors-reversed ...) mutators super-type-info)))
        (define accessors (fix-first (reverse accessors-reversed)))
        (with-syntax
            ([formals
              (for/fold ([l empty])
                ([a (in-list accessors-reversed)])
                (if a
                    (list* (string->keyword (symbol->string (syntax-e a))) a l)
                    l))]
             [(field ...) accessors])
          (quasisyntax/loc stx
            (lambda formals
              (#,constructor field ...))))]
       [else
        (raise-syntax-error 'struct-keyword-constructor "Not bound to
structure info" #'struct-id)])]))

Jay

On Wed, Jun 3, 2009 at 4:58 AM, Eli Barzilay<eli at barzilay.org> wrote:
> On Jun  2, Jay McCarthy wrote:
>> The structure patterns in scheme/match have always bugged me that
>> they didn't let you put the fields in any order and you had to put
>> in _ for the fields you didn't care about.
>>
>> I've remedied this with a new match expander, struct*. I'd like to
>> put in the tree. Do people agree?
>
> But the problem with that is that it's even farther away from the
> syntax to create an instance.  Ideally, I'd like to see options to
> `define-struct' that can get you a keyword-based constructor instead
> or in addition to the positional one.  ("In addition too" is a better
> option, re the thread on renaming a constructor -- since you'll be
> able to specify the name of each constructor.)  Then define whatever
> constructor was made as a match pattern too.  Something like:
>
>  (define-struct foo (x y)
>    #:positional-constructor make-foo1
>    #:keyworded-cosntrutor make-foo2)
>
>  (match ...
>    [(make-foo1 x y) ...]
>    ;; or
>    [(make-foo2 #:x x #:y y) ...])
>
> (But I'm not sure about the syntax to define this constructor, it
> might be better to follow the syntax for functions:
>
>  (define-struct foo (#:x x #:y y))
>
> perhaps even use that to specify defaults.  But there are cases where
> you want both the positional and the keyworded versions...)
>
> --
>          ((lambda (x) (x x)) (lambda (x) (x x)))          Eli Barzilay:
>                  http://www.barzilay.org/                 Maze is Life!
>



-- 
Jay McCarthy <jay at cs.byu.edu>
Assistant Professor / Brigham Young University
http://teammccarthy.org/jay

"The glory of God is Intelligence" - D&C 93


Posted on the dev mailing list.