PasteRack.org
Paste # 7381
2019-05-03 18:07:56

Fork as a new paste.

Paste viewed 360 times.


Embed:

  1. #lang typed/racket
  2.  
  3. (require (for-syntax racket/syntax
  4.                      racket/list
  5.                      syntax/parse))
  6.  
  7. (provide struct/fields)
  8.  
  9.  
  10. (begin-for-syntax
  11.   (define (syntax->keyword stx)
  12.     (string->keyword (symbol->string (syntax->datum stx)))))
  13.  
  14. (define-syntax struct/fields
  15.   (syntax-parser
  16.     [(_ id ([field : type] ...))
  17.      (with-syntax ([constructor/kw (format-id #'id "~a/kw" #'id)]
  18.                    [constructor/fields (format-id #'id "~a/fields" #'id)]
  19.                    [(kw+type ...) (append*
  20.                                    (map (lambda (fld type)
  21.                                           (list (syntax->keyword fld)
  22.                                                 type))
  23.                                         (syntax->list #'(field ...))
  24.                                         (syntax->list #'(type ...))))]
  25.                    [(kw+field ...) (append*
  26.                                     (map (lambda (fld)
  27.                                            (list (syntax->keyword fld)
  28.                                                  fld))
  29.                                          (syntax->list #'(field ...))))]
  30.                    [ooo #'(... ...)])
  31.        #'(begin
  32.            (struct id ([field : type] ...))
  33.            (define constructor/kw
  34.              (ann (lambda (kw+field ...)
  35.                     (id field ...))
  36.                   (kw+type ... -> id)))
  37.            (define-syntax constructor/fields
  38.              (syntax-parser
  39.                [(_ [fld val] ooo)
  40.                 #'(cons constructor/kw (flatten (list (syntax->keyword #'fld) val) ooo))]))))]))
  41.  
  42. (struct/fields
  43.  foo
  44.  ([a : Integer]
  45.   [b : Symbol]))
  46.  
  47. (foo/fields
  48.  [b 'x]
  49.  [a 5])

=>