{"size": 3410, "ext": "scrbl", "max_stars_repo_path": "base/variant.scrbl", "max_stars_repo_name": "9999years/rebellion", "max_stars_repo_stars_event_min_datetime": "2019-05-28T21:50:27.000Z", "max_stars_repo_stars_event_max_datetime": "2022-03-17T21:21:52.000Z", "max_issues_repo_path": "base/variant.scrbl", "max_issues_repo_name": "9999years/rebellion", "max_issues_repo_issues_event_min_datetime": "2019-03-02T23:19:07.000Z", "max_issues_repo_issues_event_max_datetime": "2022-01-24T08:43:16.000Z", "max_forks_repo_path": "base/variant.scrbl", "max_forks_repo_name": "9999years/rebellion", "max_forks_repo_forks_event_min_datetime": "2019-02-01T22:21:26.000Z", "max_forks_repo_forks_event_max_datetime": "2022-01-24T04:35:35.000Z"}
{"max_stars_count": 73, "max_issues_count": 216, "max_forks_count": 20, "avg_line_length": 34.7959183673, "max_line_length": 80, "alphanum_fraction": 0.6589442815}
#lang scribble/manual

@(require (for-label racket/base
                     racket/contract/base
                     racket/contract/region
                     racket/match
                     rebellion/base/variant)
          (submod rebellion/private/scribble-cross-document-tech doc)
          (submod rebellion/private/scribble-evaluator-factory doc)
          scribble/example)

@(define make-evaluator
   (make-module-sharing-evaluator-factory
    #:public (list 'racket/match
                   'racket/contract/base
                   'racket/contract/region
                   'rebellion/base/variant)
    #:private (list 'racket/base)))

@title{Variants}
@defmodule[rebellion/base/variant]

A @deftech{variant} is a value tagged with a keyword. Variants are used to
distinguish different kinds of values by name, without knowing anything about
the types of those values.

@defproc[(variant? [v any/c]) variant?]{
 A predicate for @tech{variants}.}

@defproc[(variant [#:<kw> v any/c]) variant?]{
 Constructs a @tech{variant} containing @racket[v] tagged with the given
 keyword, where @racket[#:<kw>] stands for any keyword.

 @(examples
   #:eval (make-evaluator) #:once
   (variant #:success 42)
   (variant #:failure "oops"))

 Additionally, the @racket[variant] constructor may be used as a
 @tech/reference{match expander}.

 @(examples
   #:eval (make-evaluator) #:once
   (eval:no-prompt
    (define (try-add1 v)
      (match v
        [(variant #:success x) (add1 x)]
        [(variant #:failure msg) (error msg)])))

   (try-add1 (variant #:success 42))
   (eval:error (try-add1 (variant #:failure "oops"))))}

@defproc[(variant-value [var variant?]) any/c]{
 Returns the value contained in @racket[var].

 @(examples
   #:eval (make-evaluator) #:once
   (variant-value (variant #:success 42))
   (variant-value (variant #:failure "oops")))}

@defproc[(variant-tag [var variant?]) keyword?]{
 Returns the tag keyword of @racket[var].

 @(examples
   #:eval (make-evaluator) #:once
   (variant-tag (variant #:success 42))
   (variant-tag (variant #:failure "oops")))}

@defproc[(variant-tagged-as? [var variant?] [tag-keyword keyword?]) boolean?]{
 Returns @racket[#t] if @racket[var] is tagged with @racket[tag-keyword],
 returns @racket[#f] otherwise.

 @(examples
   #:eval (make-evaluator) #:once
   (variant-tagged-as? (variant #:success 42) '#:success)
   (variant-tagged-as? (variant #:success 42) '#:failure))}

@defproc[(variant/c [#:<kw> case-contract contract?] ...) contract?]{
 A @tech/reference{contract combinator} for @tech{variants}. Returns a contract
 that enforces that the contracted value is a variant tagged with one of the
 given @racket[#:<kw>]s. If it is, then the corresponding @racket[case-contract]
 is used to check the variant's value. If every @racket[case-contract] is a
 @tech/reference{flat contract} then the returned contract is as well, and
 likewise for @tech/reference{chaperone contracts}.

 @(examples
   #:eval (make-evaluator) #:once
   (eval:no-prompt
    (define/contract (get-success-or-zero var)
      (-> (variant/c #:success number? #:failure string?) number?)
      (match var
        [(variant #:success x) x]
        [(variant #:failure _) 0])))

   (get-success-or-zero (variant #:success 42))
   (eval:error (get-success-or-zero (variant #:success "not a number")))
   (eval:error (get-success-or-zero (variant #:other "whoops"))))}
