On this page:
9.1 Introduction
9.2 Implementation of variant
«constructor-or-tagged-stx-class»
«variant»
9.3 Predicate
«variant?»
9.4 define-variant
«define-variant»
9.5 Conclusion
«*»
7.1

9 User API for variants

    9.1 Introduction

    9.2 Implementation of variant

    9.3 Predicate

    9.4 define-variant

    9.5 Conclusion

9.1 Introduction

For convenience, we write a variant form, which is a thin wrapper against (U (~or constructor tagged) ).

9.2 Implementation of variant

In define-variant, we only define the type (which is the union of all the possible constructors. We do not bind identifiers for the constructors, for two reasons: the same constructors could appear in several variants, so we would define them twice, and it is likely that a constructor will have the same identifier as an existing variable or function.

(begin-for-syntax
  (define-syntax-class constructor-or-tagged
    (pattern [constructor-name:id . (~or ([field:id C:colon type:expr] )
                                         (type:expr ))])))

(define-type-expander (variant stx)
  (syntax-parse stx
    [(_ :constructor-or-tagged )
     (template
      (U (?? (tagged constructor-name [field C type] )
             (constructor constructor-name type ))
         ))]))

9.3 Predicate

(define-syntax/parse (variant? :constructor-or-tagged )
  (template
   (λ (v) (or (?? ((tagged? constructor-name field ) v)
                  (constructor? constructor-name v))
              ))))

9.4 define-variant

(define-syntax/parse
    (define-variant variant-name
      (~optkw #:debug)
      (~maybe #:? name?)
      (~maybe #:match variant-match)
      (~and constructor-or-tagged :constructor-or-tagged) )
  (define/with-syntax default-name? (format-id #'name "~a?" #'name))
  (define/with-syntax default-match (format-id #'name "~a-match" #'name))
  (define-temp-ids "pat" ((type ) ))
  (define-temp-ids "match-body" (constructor-name ))
  (template
   (begin
     (define-type variant-name
       (variant [constructor-name (?? ([email protected] [field C type] )
                                      ([email protected] type ))]
                ))
     (define-syntax (?? variant-match default-match)
       (syntax-rules (constructor-name  (?? ([email protected] field )) )
         [(_ v
             [(constructor-name (?? ([email protected] [field pat] )
                                    (pat )))
              . match-body]
             )
          (match v
            (?? [(tagged constructor-name [field pat] ) . match-body]
                [(constructor constructor-name pat ) . match-body])
            )]))
     (define-multi-id (?? name? default-name?)
       #:else
       #'(variant? constructor-or-tagged )))))

9.5 Conclusion

«*» ::=
(require (for-syntax racket/base
                     racket/list
                     syntax/parse
                     syntax/parse/experimental/template
                     racket/syntax
                     phc-toolkit/untyped
                     type-expander/expander)
         phc-toolkit
         multi-id
         type-expander
         "constructor.hl.rkt"
         "structure.hl.rkt")
 
(provide variant
         variant?
         define-variant)
 
«constructor-or-tagged-stx-class»
«variant»
«variant?»
«define-variant»