>
> 2) (card (line . xs)) has only one field, xs. Of course, you could also
> define it as a normal field which contains a list, but there's some other
> scenarios where I found it more elegant to represent it as a dotted
> argument (like representing s-expressions as a struct).
>
Oh sorry, that was a typo. I meant currently you expect

> (card (line . xs))
> (line 1 2 3 4 5 6 7 8 9)
(line 1 2 3 4 5 6 7 8 9)

to be the output, but I was asking if:

> (card (line . xs))
> (line 1 2 3 4 5 6 7 8 9)
(line '(1 2 3 4 5 6 7 8 9))

makes more sense. In any case, your response clears things up that there is
indeed only one field. You simply want it to be printed like that.

This is actually a pretty fun problem. Here’s a quick prototype. Dropping
it here in case anyone is interested:

#lang racket

(require syntax/parse/define
         (for-syntax syntax/parse/lib/function-header
                     racket/syntax
                     racket/list
                     racket/struct-info))

(begin-for-syntax
  (struct my-struct-info (fields args ctor)
    #:property prop:procedure
    (λ (inst stx)
      (syntax-parse stx
        [(_ args ...) #`(#,(my-struct-info-ctor inst) args ...)]
        [x:id #'#,(my-struct-info-ctor inst)]))))

(define-syntax-parse-rule (define-accessors+predicate
                            {~var struct-id (static values #f)}
                            name:id)
  #:with (fields ...) (struct-field-info-list (attribute struct-id.value))
  #:do [(define the-struct-info (extract-struct-info (attribute
struct-id.value)))]
  #:with predicate (list-ref the-struct-info 2)
  #:with (accessors ...) (list-ref the-struct-info 3)
  #:with new-predicate (format-id #'name "~a?" #'name)
  #:with (new-accessors ...)
  (map (λ (id) (format-id #'name "~a-~a" #'name id)) (attribute fields))

  (begin
    (define new-predicate predicate)
    (define new-accessors accessors) ...))

(define-syntax-parse-rule
  (card
   {~optional (~var super-id (static my-struct-info? "card type"))}
   {~and header:function-header (_:id . args)})

  #:with ((all-fields ...) all-args)
  (let ([info (attribute super-id.value)])
    (cond
      [info
       (unless (list? (syntax-e (my-struct-info-args info)))
         (raise-syntax-error 'card
                             "supertype can't have variadic fields"
                             this-syntax))
       #`(({~@ . #,(my-struct-info-fields info)} . header.params)
          ({~@ . #,(my-struct-info-args info)} . args))]
      [else #'(header.params args)]))

  #:fail-when (check-duplicates (attribute all-fields) #:key syntax-e)
  "duplicate field name"

  (begin
    (struct shadow (all-fields ...)
      #:transparent
      ;; TODO: implement gen:custom-write (probably with
make-constructor-style-printer)
      ;; to customize struct value printing
      #:reflection-name 'header.name)
    (define-accessors+predicate shadow header.name)
    (define (shadow-ctor . all-args)
      (shadow all-fields ...))
    (define-syntax header.name
      (my-struct-info #'(all-fields ...)
                      #'all-args
                      #'shadow-ctor))))

(let ()
  (card (hola a b #:c c))
  (println (hola 1 2 #:c 3))

  (card (ciao a [b 3]))
  (println (ciao 7))
  (println (ciao 7 4))

  (card (line . xs))
  (println (line 1 2 3 4 5 6 7 8 9)))

(let ()
  (card (hola a #:b b))
  (card hola (ciao c))
  (define v (ciao 1 #:b 2 3))
  (println v)
  (println (list (ciao-a v) (ciao-b v) (ciao-c v)))
  (println (list (ciao? v) (hola? v))))

(let ()
  (card (foo . xs))
  ;; uncomment should result in a syntax error
  (card #;foo (bar . ys))

  (card (a xs))
  ;; uncomment should result in a syntax error
  (card #;a (b xs))

  (void))

What I did not implement is making the struct value printed in the way you
want, but that can be adjusted by using gen:custom-write. Note that I
didn’t (re)use struct‘s supertype feature since you want fields in the
opposite order.

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-users/CADcuegvDpWqFACR1CQ9Z48GQdvpgkpk2pJTVBzj-t3zojr9nkg%40mail.gmail.com.

Reply via email to