>
> 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.